JavaプログラマがXcodeでiPhoneアプリを作ってみる.6週目

せっかくなので関数型で書いてみる

何も考えずにSwiftを書いているといつものオブジェクト指向で書いてしまいます。せっかくなのでArrayクラスで関数型の書き方を試してみます。



Array.map()

map()は配列の各要素に同じ処理を繰り返す場合に使用します。
メドッド名が何故map()なのかニュアンスがよくわかりません。

1.関数型言語は関数を引数で渡せます。

//100を足して返す関数

func plus100(srcVal:Int) -> Int {
  return srcVal + 100
}

//Arrayのmapメソッドに関数を渡す

let srcArray = [1, 2, 3, ]
var array1 = srcArray.map(plus100)
XCTAssertEqual(array1[0], 101, "Pass")
XCTAssertEqual(array1[1], 102, "Pass")
XCTAssertEqual(array1[2], 103, "Pass")


2.同じ処理をクロージャでも書けます
変数名とか型を省略して書くとこんな感じになります

let srcArray = [1, 2, 3, ]
let array2 = srcArray.map{ $0 + 100 }
XCTAssertEqual(array2[0], 101, "Pass")
XCTAssertEqual(array2[1], 102, "Pass")
XCTAssertEqual(array2[2], 103, "Pass")


3.変数名と型を明示して書くこともできます。これだと戻り値の型を変えられます。

var array3 = srcArray.map{(srcVal:Int) -> String in
  return String(srcVal + 100)
}
XCTAssertEqual(array3[0], "101", "Pass")
XCTAssertEqual(array3[1], "102", "Pass")
XCTAssertEqual(array3[2], "103", "Pass")


4.クロージャはブロックの外の変数にアクセス可能です

var before = 0
var 配列の一つ前の要素と合計 = srcArray.map{(srcVal:Int) -> Int in
  let now = before + srcVal
  before = srcVal
  return now
}
XCTAssertEqual(配列の一つ前の要素と合計[0], 1, "Pass") //0 + 1
XCTAssertEqual(配列の一つ前の要素と合計[1], 3, "Pass") //1 + 2
XCTAssertEqual(配列の一つ前の要素と合計[2], 5, "Pass") //2 + 3
Array.filter()

filterは、文字通り任意の基準で配列の要素を抽出するのに使用します。

let srcArray = [1, 2, 3, 4, 5, 6, 7, 8, 9,]

let 3の倍数 = srcArray.filter{ $0 % 3 == 0 }
XCTAssertEqual(3の倍数[0], 3, "Pass")
XCTAssertEqual(3の倍数[1], 6, "Pass")
XCTAssertEqual(3の倍数[2], 9, "Pass")
XCTAssertEqual(3の倍数.count, 3, "Pass")
Array.reduce()

reduceは前のループの結果を受けて次のループを処理するときに使用する感じでしょうか?
最初の引数の値は初期値となります

let srcArray = [1, 2, 3, ]
let sum1 = srcArray.reduce(0) { $0 + $1 }
XCTAssertEqual(sum1, 6, "Pass") //初期値0 + 1 + 2 + 3

let sum2 = srcArray.reduce(100) { $0 + $1 }
XCTAssertEqual(sum2, 106, "Pass") //初期値100 + 1 + 2 + 3
Array.sorted()

最後はソートです。sortedだと新たなリストを返しますが、sort()だと元の配列自体が並び替えられます。

var srcArray = [3, 1, 4, 2,]
    
let ソートしてみた = srcArray.sorted({ $0 < $1 })
XCTAssertEqual(ソートしてみた[0], 1, "Pass")
XCTAssertEqual(ソートしてみた[1], 2, "Pass")
XCTAssertEqual(ソートしてみた[2], 3, "Pass")
XCTAssertEqual(ソートしてみた[3], 4, "Pass")
おまけ

Arrayのコード補完で表示されるメソッドのうち、関数が渡せるメソッドはあと2つあります。Array.withUnsafeBufferPointer(),ArrayとArray.withUnsafeMutableBufferPointer()です。ググっても情報がありません。かなりフレームワークよりの機能なのでしょうか?