関数を返す関数
前回のエントリでは関数を引数にとる関数が出てきたけど、今度は関数を返す関数(これも高階関数だ)が出てきた。
(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)
うまくいった!