「詳解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」の方が読みやすいと思ったのでこちらを買いました。
■追記
少し勉強して分かったこと。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全体にわたる基本概念だから読んだ方がいい
*1:オプショナル型だけはちゃんと理解する必要あり。