読者です 読者をやめる 読者になる 読者になる

woshidan's blog

そんなことよりコードにダイブ。

はてな教科書の「プログラミング言語 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から。