Scheme入門 第11章 黒じゃあー!
さて前回は、関数を渡す関数というものが作れることを説明しました。今回は、関数を返す関数も作ってみましょう。もちろん無名関数を作る lambda を使ってね。
(define (f) (lambda (x) (+ x 1)))
この関数 f は (lambda (x) (+ x 1)) を返すはずです。(lambda (x) (+ x 1)) は値を1だけ増やす関数(相変わらず芸が無いというか…)ですから、f は値を1だけ増やす関数を返すはずです。試してみましょうか。
(display ((f) 4))
(f) は関数を返しますから、((f) 4) でその関数を呼び出せるはずです。

結果は期待通り 5 が表示されます。では次の例もご覧下さいませ。
(define (f y) (lambda (x) (+ x y)))
x に y を足す関数を返す関数 f。y って、無名関数じゃなくて f の引数ですけど、大丈夫なんでしょうか。
(define (f y) (lambda (x) (+ x y)))
(display ((f 4) 5))

9 と表示されます。どうやら大丈夫なようです。じゃあ、関数を変数に保存しておいて、後で使ってみるとか。
(define (f y) (lambda (x) (+ x y)))
(define inc4 (f 4))
(display (inc4 5))

結果はやはり 9。全然平気です。f の中で作られた関数は、f に渡した y の値を覚えているようです。この仕組みをクロージャと呼びます。関数は、そのプログラムの中身の他に、関連する変数も持っているのです。
この変数は、作られた関数が消滅するまで存在していることになります。
クロージャの性質を示す良い例として、カウンターを紹介しましょう。関数 make-counter に初期値を与えると、関数を返します。この関数は、呼び出すたびに値が1ずつ増えていくのです。
(define (make-counter x)
(lambda ()
(set! x (+ x 1))
x))
(define counter (make-counter 0))
(display (counter))(newline)
(display (counter))(newline)
(display (counter))(newline)
counter を呼び出すたびに1ずつ増えていくと思います。

make-counter が呼ばれたときの x を counter が覚えていて、呼び出すごとに set! で値を更新していくためです。なかなか奇妙なものですね。クロージャを利用すると色々と面白いことが出来ますが、それはまたの機会に。
第11章・完
第12章へ

![]() |
- DrScheme での Language Pack の選択
- Scheme の単純な式「(+ 3 2)」, 「(- 10 4)」
- Scheme の単純な式(括弧の入れ子)
- Scheme の単純な式 (DrScheme の定義ウインドウ)
- 関数 area-of-disk の定義と,関数適用
- 関数 area-of-disk,変数 PI の定義と,関数適用(1)
- 関数 area-of-disk,変数 PI の定義と,関数適用(2)

0 コメント:
コメントを投稿