関数を返す関数
前回のエントリでは関数を引数にとる関数が出てきたけど、今度は関数を返す関数(これも高階関数だ)が出てきた。
(define eq?-c
  (lambda (a)
    (lambda (x)
      (eq? x a))))
この関数 eq?-c は a を引数にとり、「x を引数にとって a と比較する関数」を返す。
「これは『カリー化』(Curry-ing)と呼ばれています。」って、カリー化の説明これだけ?
カリー化とは、本来複数の引数を取る関数を引数の一部だけとって「残りの引数を取る関数」を返す関数に変更、というか変換すること、だと理解している。そう間違ってはいないはず。この例の場合では2引数の関数 eq? をカリー化した関数が eq?-c ってわけだ。
返ってくるのが関数だから、名前をつけてやれば普通の関数として使える。
gosh> (define eq?-c
  (lambda (a)
    (lambda (x)
      (eq? x a))))
eq?-c
gosh> (define eq?-salad (eq?-c 'salad))
eq?-salad
gosh> (eq?-salad 'salad)
#t
gosh> (eq?-salad 'tuna)
#f
とはいえ、必要がなければ名前をつけてやることもない。こんなふうにも書ける。
gosh> ((eq?-c 'salad) 'salad) #t
ふたたび rember-f
で、今度は、rember-f を比較関数 test? を引数にとって「a と l を引数にとる関数」を返す関数に書き直せ、ときた。うん、たぶん書けるだろう。
(define rember-f
  (lambda (test?)
    (lambda (a l)
      (cond
        ((null? l) (quote ()))
        ((test? (car l) a) (cdr l))
        (else (cons (car l) ((rember-f test?) a (cdr l))))))))
(print ((rember-f eq?) 'tuna '(shrimp salad and tuna salad)))
^o^ > gosh rember-f2.scm (shrimp salad and salad)
うまくいった!
「関数を返す関数」への1件のフィードバック