lispで無名関数

Lispで無名関数の実装方法について学んだのでまとめてみる。

無名関数とは

関数型言語の利点は関数をデータとして扱えるところである。データとして扱えるとはどういうことかというと、変数に関数を代入できるといったようなことができるわけである。なので引数として関数を受け取るような関数を作ることもできる。
となってくると、変数に代入するだけの、一時的にしか使われない関数を毎回名前を付けて定義するのは面倒になってくる。
そこで登場するのが無名関数だ。このような一時的に使用するような関数を一時的に定義することができる。

実装方法

Lispでの実装方法は以下のようになる

#'(lambda ("引数") "本体")

これで無名関数が作られる。
例えば、引数xと引数yの積を返すような無名関数を定義する場合はこのようにすれば良い。

#'(lambda (x y) (* x y)) 

といったようになる。ではこの関数を変数に代入し実際に動かしてみよう。

(setf fun #'(lambda (x y) (* x y)))
(funcall fun 3 2)

まずsetfを使いfunに無名関数を代入する。その後にfuncallを用いて変数funを評価することによって関数を評価させることができる。注意としては(fun 3 2)のようにしても関数は動かないところである。
関数を評価する関数として他にもapplyがある。funcallとの違いは機会があれば今後説明したい。(めんどくさいわけではない)

関数を引数に取る関数

ここで簡単な関数を引数として取る関数を実装する。

(defun test (fun a b)
  (list (funcall fun a b) (funcall fun b a))
)

このtest関数は関数funを引数として受け取り、funの引数にa,bをとった時の結果とb,aをとった時の結果をリストにして返す。実行例は

CL-USER> (test #'/ 1 2)
(1/2 2)
CL-USER> (test #'- 1 2)
(-1 1)

である。#'/と#'-は関数/と-をデータして渡している。
自作した無名関数を代入する場合は

CL-USER> (test #'(lambda (x y) (list x y)) 3 4)
((3 4) (4 3))

となる。
次回はlispのこの関数型言語という特性を活かして、前回紹介したマージソートを拡張していきたい。