Swift のクロージャと Ruby の lambda

ここで Swift におけるクロージャの使い方が説明されています。

こちらで同じ内容のコードを再掲するとこんな感じでしょうか。Swift 4.0。

func f(_ a: Int, _ b: Int, _ closure: (Int, Int) -> Int) -> Int { 
    return closure(a, b) 
} 

print(f(1, 2, {a, b in return a + b}))    //=>3
print(f(1, 2, {$0 + $1}))    //=>3
print(f(1, 2, +))            //=>3

print(f(1, 2) {a, b in return a + b})     //=>3

func addNumber(_ number: Int) -> () -> Int {
    var sum = 0
    func add() -> Int {
        sum += number
        return sum
    }
    return add
}

let addTen = addNumber(10)
print(addTen())    //=>10
print(addTen())    //=>20

let addSeven = addNumber(7)
print(addSeven())  //=>7
print(addSeven())  //=>14
print(addTen())    //=>30

 
これらは Ruby の lambda でも基本的に同じことができます。Ruby の lambda はもちろんクロージャで、第一級関数(first class の関数)ですからね。つまり、変数に代入したり、関数の引数になったり返り値になったりできます。

f = ->(a, b, closure) {closure[a, b]}

p f[1, 2, ->(a, b) {a + b}]    #=>3


add_number = ->(number) {
  sum = 0
  -> {sum += number}
}

add_ten = add_number[10]
p add_ten[]    #=>10
p add_ten[]    #=>20

add_seven = add_number[7]
p add_seven[]  #=>7
p add_seven[]  #=>14
p add_ten[]    #=>30

Ruby の簡潔さがここでも出ているのではないでしょうか。

同じことはもちろん JavaScript でも Python でも可能です。


しかし、Swift はいい言語ですね。ここでも見られるように、 Ruby の「ブロック」と同等の機能を、Ruby と同じくらい可読性の高い形で書けるというのはすばらしい。クロージャの中に引数を書くのは、Swift の開発者の言っているとおり、Ruby のパクリですね。いや、上手くパクったと思います。それから、この記事とは関係ないですが、Swift の「オプショナル型」は Ruby にはないものですね。Rubynil 関連のエラーは結構よく出るので、「オプショナル型」ってのはいい考えに思えます。もちろんより安全性が高まるというのはより面倒になるということで、Swift の融通の効かなさがかなわないこともありますが、これは盾の両面で、どちらかというと Swift のこの点の面倒さは大規模開発とかに有利に効いてくるでしょう。Rubynil の安全性を高めるためにいわゆる「ぼっち演算子」(safe navigation operator)を導入したくらいですし。

Ruby の lambda についてはこちらも。