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 コメント:
コメントを投稿