Common Lisp には実際に使ってみないと効果がよくわからない謎機能があったりしますが、そのなかでもぶっちぎりのイミフ機能が以外と実用できることがわかったので書いておきます。
lambda form とは、フォームの先頭が、通常のように関数名ではなく (lambda (...)...) であるようなフォームのことです。 haskellなんかではよく見ますね。
(funcall (lambda (x) (* 2 x)) 10) ;--> 20 lambda 使うならこれがふつう mapcarとか
((lambda (x) (* 2 x)) 10) ;--> 20 (λx.2*x) 10 かな?
(* 2 10) ;--> 20
これら3つの式が同一であることは、ある程度ほにゃら計算がどーたらってことを聞きかじっていれば、その理論的/歴史的重要性はわかるのですが、clのユーザがコードを書く上での利便性というものはほとんど認識していませんでした。
Take 1
今回見出した使いドコロは特にこんな時。
(let ((x (if (SUPER-COOL-FUNCTION-WITH-SUPER-LONG-NAME
'SUPER-CALIFRAGILISTIC-EXPIARI-DOCIOUS
:lots 'of :keyword '(arguments that extends)
:even into-the-fourth-line)
(even-longer-function-with-enough-number-of-arguments
acc (cdr list) list2)
(even-longer-function-with-enough-number-of-arguments
acc list (cdr list2)))
(if (evenp x)
`(/ ,x 2)
x))
頭でっかちで格好わるい。
しかし、ある意味、分岐はxの値がわからないとできないので、こうなってしまうのは仕方がないといえば仕方がない。
Take 2
関数型なんだから全部書き下せば....いやだめだろこれ。
(if (evenp (if (SUPER-COOL-FUNCTION-WITH-SUPER-LONG-NAME
'SUPER-CALIFRAGILISTIC-EXPIARI-DOCIOUS
:lots 'of :keyword '(arguments that extends)
:even into-the-fourth-line)
(even-longer-function-with-enough-number-of-arguments
acc (cdr list) list2)
(even-longer-function-with-enough-number-of-arguments
acc list (cdr list2)))
`(/ ,(if (SUPER-COOL-FUNCTION-WITH-SUPER-LONG-NAME
'SUPER-CALIFRAGILISTIC-EXPIARI-DOCIOUS
:lots 'of :keyword '(arguments that extends)
:even into-the-fourth-line)
(even-longer-function-with-enough-number-of-arguments
acc (cdr list) list2)
(even-longer-function-with-enough-number-of-arguments
acc list (cdr list2)) 2)
(if (SUPER-COOL-FUNCTION-WITH-SUPER-LONG-NAME
'SUPER-CALIFRAGILISTIC-EXPIARI-DOCIOUS
:lots 'of :keyword '(arguments that extends)
:even into-the-fourth-line)
(even-longer-function-with-enough-number-of-arguments
acc (cdr list) list2)
(even-longer-function-with-enough-number-of-arguments
acc list (cdr list2))))
本当は、いわゆる後方参照みたいなのが書きたいわけです。
それに、たかがこんなののために遅延評価つかうのは面倒くさいし...
Take 3 Lambda Form
ということで正解はこれ。
((lambda (x)
(if (evenp x)
`(/ ,x 2)
x)))
(if (SUPER-COOL-FUNCTION-WITH-SUPER-LONG-NAME
'SUPER-CALIFRAGILISTIC-EXPIARI-DOCIOUS
:lots 'of :keyword '(arguments that extends)
:even into-the-fourth-line)
(even-longer-function-with-enough-number-of-arguments
acc (cdr list) list2)
(even-longer-function-with-enough-number-of-arguments
acc list (cdr list2)))))
lambdaとletでできることは本質的には一緒なので、こういうことができるのは当然ですが、lispを書いていると、メインの処理ほど右下に書きたくなりますよね。そんな場合にどうぞ。
書捨て御免!