3
3

More than 5 years have passed since last update.

lambda フォームの使いどころ

Last updated at Posted at 2015-03-11

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を書いていると、メインの処理ほど右下に書きたくなりますよね。そんな場合にどうぞ。

書捨て御免!

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3