Advanced Coding

関数シンボル

すでに定義されている関数のシンボルを取得し,実行することができます. C言語で言うところの関数ポインタに当たります. 関数シンボルは#'で取得することができます.

無名関数(lambda)

関数シンボルと組み合わせることで, その場で関数の内容を定義して渡すことができます.

通常の関数定義は以下のようになりますが,

(defun funcname (args) (do-something))

無名関数の定義は以下のようになります.

(lambda (args) (do-something))

sort

関数シンボルを用いる例として,sortがあります. その名の通りソートを行う関数ですが, 比較評価のための関数シンボルを受け取り昇順,降順などを決めることができます.

例えば,以下の例を実行してみてください.

(setq *ls* (list 0 3 1 2))
(print (sort *ls* #'<))
(print (sort *ls* #'>))

最初のソートは,<の関数シンボルを与えていて,リストは昇順に並びます. 次のソートは>の関数シンボルを与えていて,リストは降順に並びます.

sortは破壊的メソッドなので中身が書き換わることに注意してください.

mapcar

mapcarは関数シンボルを用いてリストに対して処理を行うことができます. 渡された関数シンボルの内容をリストの各要素に適用していきます.

以下の例では,無名関数で与えられた値を二倍するようにし,リストの要素をすべて二倍にします.

(mapcar #'(lambda (x) (* 2 x)) (list 0 3 1 2))
;; (0 6 2 4)

funcall

関数シンボルを実行するにはfuncallを使います.

(defun numcheck (a b func) (if (funcall func a b) a b))

この例では,与えられた2つの値を比較する関数シンボルfuncを受け取り, その値が真になればa,偽になればbを返すようにしています. 次の実行結果を確認してみてください.

(numcheck 0 1 #'<)  ;; 0
(numcheck 0 1 #'>)  ;; 1