「詳解Swift」という本を買って、サンプルを打ち込んで勉強中。今はデータ型を理解。。Swiftは型チェックが厳しく、また暗黙の型変換はなされない、ということで、型変換の関数(正確には関数ではなくイニシャライザらしい)が用意されている。Character型は1文字でString型は複数文字とのことで違いがよく分からない(なぜわざわざ1文字のCharacter型を作ったのか)(Cで言うところの、char / char[]の違いではなさそうだし)のだが、、分からないなりに無理やりString->Characterに変換させてみた。すると、、Fatal errorでスタックトレースが表示された。たしかに誤った操作でエラーかもしれないが、、、容易に発生しうる間違った型変換と思うのですが、スタックトレースしますかね。。それほど許せない操作なのか??
7> Character("hello")
Fatal error: Can't form a Character from a String containing more than one extended grapheme cluster: file Swift/Character.swift, line 177
Current stack trace:
0 libswiftCore.so 0x00007ffff7c21810 swift_reportError + 50
1 libswiftCore.so 0x00007ffff7c95370 _swift_stdlib_reportFatalErrorInFile + 115
2 libswiftCore.so 0x00007ffff797a16e <unavailable> + 1397102
3 libswiftCore.so 0x00007ffff7979cc7 <unavailable> + 1395911
4 libswiftCore.so 0x00007ffff79799a3 <unavailable> + 1395107
5 libswiftCore.so 0x00007ffff7979410 _assertionFailure(_:_:file:line:flags:) + 511
6 libswiftCore.so 0x00007ffff797989c <unavailable> + 1394844
7 libswiftCore.so 0x00007ffff79873a0 Character.init(_:) + 290
Execution interrupted. Enter code to recover and continue.
Enter LLDB commands to investigate (type :help for assistance.)
ちなみに、、動かしているのはMac上ではなく、WIndows上のUbuntuにswiftを入れてインタプリタモード(REPL)で動かしている。MAC OSだとこうはならないのだろうか。
■補足
勉強のため「詳解Swift」という本を買いました。本屋で「実践Swift」と読み比べたけど、どちらも同じような細かさの解説本と思いました。フォントのせいなのかレイアウトのせいなのか分かりませんが、ぱっと見た感じ、「詳解Swift」の方が読みやすいと思ったのでこちらを買いました。
確かにページ数も多いですが、基本的な説明と、メモリ管理、拡張(extention)、
ジェネリクス等、高度な概念に分かれており、まず基本部分をざっと読めば最低のコードは組めるのではと期待
*1。。章立てがうまくなされているので、基本仕様の解説を選んで、サンプルを打ち込みながら勉強することが可能。細かすぎて辞書のようにしか使えないということはありません。まだ少ししか読んでいませんが、筆者(萩原氏)の思いが伝わってくる本です。
■追記
少し勉強して分かったこと。swiftのソースコードを見ていると、頻繁に _ が出てくるけど、 _ は一体何なのかわからなった。 _ とは、使わない、指定しない、捨てる等、 無 を表すキーワードであった。
あと、文字列操作がめちゃくちゃめんどくさいことが分かった。 "abc"[3]のようなことは書けない、Stringの位置を指定するには、Index型を作って位置指定が必要であった。さらに、位置指定で取り出された結果はString型ではなくて、String.SubSequenc型であった。StringイニシャライザでString型に変換が必要らしかった。 勉強を兼ねてsubstringを書くと以下のようになると思う。もっと勉強すると、関数の冒頭でguardとか使えると思うが。
Swiftで書いた文字列抜き取り関数
func substring(_ str:String, _ start:Int, _ len:Int) -> String? {
if start > (str.count - 1){
return nil
}
if (start + len - 1) > (str.count - 1){
return nil
}
let from = str.index(str.startIndex, offsetBy:start)
let to = str.index(str.startIndex, offsetBy: start + len)
let pick = String(str[from ..< to])
return pick
}
prefixとsuffixを組み合わせたバージョン
func substring(_ str:String, _ start:Int, _ len:Int) -> String? {
if start > (str.count - 1){
return nil
}
if (start + len - 1) > (str.count - 1){
return nil
}
let pick = str.suffix(str.count - start) // 文字列末尾から切り取る
return String(pick.prefix(len)) //文字列先頭から切り取る
}
Swiftは型にとことんこだわる言語ということで、気をぬいて実装するとすぐに型不一致で怒られるだろう。型を確認する関数を作った。
func showType<T>(_ tgt:T){
print("type is",type(of: tgt))
}
■追記
クロージャを勉強。クロージャサンプルを作ってみる。。。UDP通信のコールバックはクロージャで表現されていると思う。多分。。
//クロージャ型変数を定義
var cat : (String, String) -> String
//クロージャを定義して変数に代入
cat = { "!!>>\($0), \($1)<<!!" }
print(cat("hello","bye")) // クロージャを実行
//クロージャを引数とする関数を定義
func test(_ str1:String, _ str2:String, by clos:(String,String)->String) -> String {
clos(str1, str2)
}
print(test("foo", "bar", by:cat)) // 関数を実行
print(test("aaa","bbb", by:{ "__\($0),\($1)__" }))
// 接尾クロージャ (trailing closure)で表現して実行
print(test("aaa","bbb"){ "_x_\($0),\($1)_x_" })
/*
output
!!>>hello, bye<<!!
!!>>foo, bar<<!!
__aaa,bbb__
_x_aaa,bbb_x_
*/
■追記
オプショナル型を学ぶ。nilを取りうる場合にoptional型を使い、値を使う時はxxx!によりラッピングを剥いて使うと理解。
//
// option
//
func showType<T>(_ tgt:T){
print("type is",type(of: tgt))
}
var x : Int? // set nil to x
var y : Int // set 0 to y
x = nil
y = 0
print("x = nil")
print("y = 0")
showType(x)
showType(y)
x = 0
y = 0
print("x = 0")
print("y = 0")
showType(x)
showType(y)
//print(y)
//if y > 0 { // ok
// print(" y > 0 ")
//}
// x > 0 // Exception
//x! // Fatal error
//x+2 // error
if x == nil {
print("nil")
}else{
print(x!)
}
print("-------------")
print("x = 1")
x = 1
if var xx = x {
showType(xx)
xx = xx + 1
print("u can use x, value:\(xx)")
}else{
showType(x)
print("u can not use x")
print("x is.. \(String(describing:x))")
}
print("-------------")
print("x = nil")
x = nil
if var xx = x {
showType(xx)
xx = xx + 1
print("u can use x, value:\(xx)")
}else{
showType(x)
print("u can not use x")
print("x is.. \(String(describing:x))")
}
print("-------------")
print("x = 1")
x = 1
if var x = x {
showType(x)
x = x + 1
print("u can use x, value:\(x)")
}else{
showType(x)
print("u can not use x")
print("x is.. \(String(describing:x))")
}
print("-------------")
print("x = nil")
x = nil
if var x = x {
showType(x)
x = x + 1
print("u can use x, value:\(x)")
}else{
showType(x)
print("u can not use x")
print("x is.. \(String(describing:x))")
}
x = nil
var val = (x != nil) ? x! : -1
print(val)
// nilcoalescing operator ??
print("-----------------")
print("nil coalescing operator \"??\"")
val = x ?? -1
showType(val)
val += 1
print(val)
//
// IUO implicitly unwrapped optional
//
print("-----------------")
print("IUO")
var xx : Int! = nil
xx = nil
if xx == nil {
print("xx is nil")
showType(xx)
print(String(describing:xx))
}else{
print("xx is not nil")
xx += 1
print(xx!)
}
xx = 1
if xx == nil {
print("xx is nil")
print(String(describing:xx))
}else{
print("xx is not nil")
showType(xx)
xx += 1
print(xx!)
}
/*********************************************:
x = nil
y = 0
type is Optional<Int>
type is Int
x = 0
y = 0
type is Optional<Int>
type is Int
0
-------------
x = 1
type is Int
u can use x, value:2
-------------
x = nil
type is Optional<Int>
u can not use x
x is.. nil
-------------
x = 1
type is Int
u can use x, value:2
-------------
x = nil
type is Optional<Int>
u can not use x
x is.. nil
-1
-----------------
nil coalescing operator "??"
type is Int
0
-----------------
IUO
xx is nil
type is Optional<Int>
nil
xx is not nil
type is Optional<Int>
2
**********************************************/
クラスの章をまったく読んでいないけど。。だんだん疲れてきたので、、文法はこれぐらいで、SwiftUIでPGしてみたい。
自分用メモ・・・プロトコルはswift全体にわたる基本概念だから読んだ方がいい