はてな教科書の「プログラミング言語 Swift」を読んでます 2
https://github.com/hatena/Hatena-Textbook/blob/master/swift-programming-language.md
のんびり読んでいきます。
Control Flow
For-In
- 範囲(cf. 0..<3)には不等号で含まれるかどうか示すことができる
- For - Inにはwhere節で渡した式が真になるもののみブロックを実行させる、といったことができる
- where節の代わりにcase文を使ってパターンマッチもできる
- パターンマッチがRubyのcaseのパターンマッチのような要注意感があるので一度パターンマッチの時の真偽について確認しておくと良さそう
1> for i in 0..<3 { 2. print(i) 3. } 0 1 2 4> for i in 0..<30 where i % 3 == 0 { 5. print("\(i):にゃー" ) 6. } 0:にゃー 3:にゃー 6:にゃー 9:にゃー 12:にゃー 15:にゃー 18:にゃー 21:にゃー 24:にゃー 27:にゃー 7> let numbers: [Int?] = [0, nil, 3, 4, nil] numbers: [Int?] = 5 values { [0] = 0 [1] = nil [2] = 3 [3] = 4 [4] = nil } 8> for case let i? in numbers { 9. print(i) 10. } 0 3 4
While
- whileも似たような形式
- continueを使って次のループの実行に移れる
- breakですべてのループの実行を終了
11> var i = 0 i: Int = 0 12> while i < 3 { 13. print(i) 14. i += 1 15. } 0 1 2 24> i = 0 25> while i < 10 { 26. if i % 3 == 0 { 27. i += 1 28. continue 29. } 30. print(i) 31. i += 1 32. } 1 2 4 5 7 8 44> i = 0 45> while i < 10 { 46. if i % 3 == 1 { 47. i += 1 48. break 49. } 50. print(i) 51. i += 1 52. } 0
Repeat-While
- do-while的な、最低でも一度は実行するwhile文
- continue, breakは通常のwhileと同じ
53> var i = 0 i: Int = 0 54> repeat { 55. print(i) 56. i += 1 57. } while i < 3 0 1 2
if
- if 条件式 {} else if 条件式 {} else {}
- if にもcaseキーワードを用いてパターンマッチができる
- Optional Binding の組み合わせがよくわからないな...
1> var number = 1 2. if case 0..<3 = number { 3. print(number) 4. } 1 number: Int = 1 6> number = 3 7. if case 0..<3 = number { 8. print(number) 9. } 24> if condition , let a : Int? = 2, let b : Int? = 3 where a != b { 25. print("true") 26. } true 27> if condition , let a : Int = 2, let b : Int = 3 where a != b { 28. print("true") 29. } true 30> if condition , let a = 2, let b = 3 where a != b { 31. print("true") 32. } repl.swift:30:16: error: initializer for conditional binding must have Optional type, not 'Int' if condition , let a = 2, let b = 3 where a != b { ^ repl.swift:30:27: error: initializer for conditional binding must have Optional type, not 'Int' if condition , let a = 2, let b = 3 where a != b {
Do
- doはスコープを作成する
- エラーハンドリングと一緒に使われることが多い
30> do { 31. let name = "John" 32. print("Hello \(name)") 33. } Hello John 34> let name = "Taylor" name: String = "Taylor" 35> print("Hello again \(name)") Hello again Taylor 36> let name = "John" // 宣言できてしまった? name: String = "John"
Functions
- 関数は引数の後ろに型を示して、シグネチャの宣言の後ろに -> で戻り値の型を示す
- 2つめ以降の引数にラベルが必須なのがほのかなObjective-Cぽさ...
- 返り値がない時はVoid型か、返り値を省略
39> func addNum(number: Int, anotherNumber: Int) -> Int { 40. return number + anotherNumber 41. } 42> let three = addNum(1, anotherNumber: 2) three: Int = 3 43> let four = addNum(1, 3 44. ) repl.swift:43:18: error: missing argument label 'anotherNumber:' in call let four = addNum(1, 3 ^ anotherNumber: 43>
関数内部で利用する引数名と外部引数名をわけることができます。
46> func multiply(number first: Int, by second: Int) -> Int { 47. return first * second 48. } 49> multiply(number: 3, by: 5) $R0: Int = 15
外部引数名として_を使うとラベルがなくなります。
50> func multiply(_ first: Int, _ second: Int) -> Int { 51. return first * second 52. } 53> multiply(3, 5) $R1: Int = 15
引数
- 関数の引数は let と同様に通常は変更できない
54> func increment(number: Int) { 55. number += 1 56. } repl.swift:55:12: error: left side of mutating operator isn't mutable: 'number' is a 'let' constant number += 1 ~~~~~~ ^
- inoutキーワードを設定することで変更可能となる
- これ、副作用を避けたい関数(?)プログラミングに多用はどうなのでしょうね...
54> func increment(inout number: Int) { 55. number += 1 56. } 57> var number = 7 number: Int = 7 58> increment(&number) 59> number $R2: Int = 8 60> increment(number) repl.swift:60:11: error: passing value of type 'Int' to an inout parameter requires explicit '&' increment(number) ^ &
引数のデフォルト値
- Kotlinのそれに近く、引数にはデフォルト値を設定でき、デフォルト値の設定された引数は呼び出し時に省略可能です
60> func say(word: String="Hello") { 61. print(word) 62. } 63> say() Hello 64> say("Hi") Hi
可変長引数
- 型名に続けて
...
と書くと可変長の引数を受けられるようになります - 実装中では
Array
型として扱われます
65> func printlines(words: String...) { 66. for word in words { 67. print(word) 68. } 69. } 70> printlines("Alice", "Bob", "Carol") Alice Bob Carol
関数型
- 関数も型として扱えて、その指定は、引数と戻り値の組であらわされます
- 例えば、
addNumbers(numbers: Int...) -> Int
なら型は(Int...) -> Int
- 戻り値に関数型を設定することもできます
- 関数に関数をネストさせて書くことも可能です
71> func addNumbers(numbers: Int...) -> Int { 72. var sum = 0 73. for number in numbers { 74. sum += number 75. } 76. return sum 77. } 78> addNumbers(1, 2, 3) $R3: Int = 6 79> var calculation : (Int...) -> Int = addNumbers calculation: (Int...) -> Int = 0x0000000101b3ec30 $__lldb_expr81`__lldb_expr_80.addNumbers (Swift.Array<Swift.Int>...) -> Swift.Int at repl.swift:71 80> calculation(1, 2, 3) $R4: Int = 6
明日はguardから。