Shammer's Philosophy

My private adversaria

funcall 実行例

そのまま定義済の関数を実行

? (funcall #'+ 1 2 3 4 5)
15
? (defun hello (name) (format t "Hello, ~A!~%" name))
HELLO
? (funcall #'hello "Taro")
Hello, Taro!
NIL
? 

lambda 式を指定する

? (funcall #'(lambda (name) (format t "Hello, ~A!~%" name)) "Taro")
Hello, Taro!
NIL
? 

何らかの方法で返された lambda 式を実行する

? (setf f #'(lambda (name) (format t "Hello, ~A!~%" name)))
#<Anonymous Function #x302000D9B48F>
? (funcall #'f "Taro")
> Error: Undefined function: F
> While executing: CCL::%FUNCTION, in process Listener(4).
> Type cmd-. to abort, cmd-\ for a list of available restarts.
> Type :? for other options.
1 > q
? (funcall f "Taro")
Hello, Taro!
NIL
? f
#<Anonymous Function #x302000D5054F>
? (setf f (lambda (name) (format t "Hello, ~A!~%" name)))
#<Anonymous Function #x302000DBC69F>
? f
#<Anonymous Function #x302000DBC69F>
? (funcall f "Taro")
Hello, Taro!
NIL
? 

lambda 式をどこかに定義する際、#' と一緒に定義してもしなくてもどちらも Anonymous Function として定義されるようだ。

どこかの要素から lambda 式を取り出す

? (defparameter x '("aaa" (lambda (name) (format t "Hello, ~A!~%" name))))
X
? x
("aaa" (LAMBDA (NAME) (FORMAT T "Hello, ~A!~%" NAME)))
? (cdr x)
((LAMBDA (NAME) (FORMAT T "Hello, ~A!~%" NAME)))
? (cadr x)
(LAMBDA (NAME) (FORMAT T "Hello, ~A!~%" NAME))
? (funcall (cadr x) "Taro")
> Error: (LAMBDA (NAME) (FORMAT T "Hello, ~A!~%" NAME)) is not of type (OR SYMBOL FUNCTION), and can't be FUNCALLed or APPLYed
> While executing: FUNCALL, in process Listener(4).
> Type cmd-. to abort, cmd-\ for a list of available restarts.
> Type :? for other options.
1 >

lambda 式を setf したとき、#' があってもなくても結果が同じだったので #' なしの lambda 式を cdr に持つリストを定義して実行してみたが、funcall は失敗した。
では、#' を付けてやればうまくいくのか?

? (defparameter x '("aaa" #'(lambda (name) (format t "Hello, ~A!~%" name))))
X
? (cadr x)
#'(LAMBDA (NAME) (FORMAT T "Hello, ~A!~%" NAME))
? (funcall (cadr x) "Taro")
> Error: #'(LAMBDA (NAME) (FORMAT T "Hello, ~A!~%" NAME)) is not of type (OR SYMBOL FUNCTION), and can't be FUNCALLed or APPLYed
> While executing: FUNCALL, in process Listener(4).
> Type cmd-. to abort, cmd-\ for a list of available restarts.
> Type :? for other options.
1 > 

違いがよくわからないが失敗。function を明示してもダメ。

? (defparameter x '("aaa" (function (lambda (name) (format t "Hello, ~A!~%" name)))))
X
? (cadr x)
#'(LAMBDA (NAME) (FORMAT T "Hello, ~A!~%" NAME))
? (funcall (cadr x) "Taro")
> Error: #'(LAMBDA (NAME) (FORMAT T "Hello, ~A!~%" NAME)) is not of type (OR SYMBOL FUNCTION), and can't be FUNCALLed or APPLYed
> While executing: FUNCALL, in process Listener(4).
> Type cmd-. to abort, cmd-\ for a list of available restarts.
> Type :? for other options.
1 >

lambda だけでなく、このやり方は他の関数もダメっぽい。

? (defparameter x '("aaa" #'+))
X
? (cadr x)
#'+
? (funcall (cadr x) 1 2 3)
> Error: #'+ is not of type (OR SYMBOL FUNCTION), and can't be FUNCALLed or APPLYed
> While executing: FUNCALL, in process Listener(4).
> Type cmd-. to abort, cmd-\ for a list of available restarts.
> Type :? for other options.
1 > 

何らかのキーを受け取り、そのキーに対応した関数を呼び出す、ということをしたい。上記の例では "aaa" がキーの想定だが、どうすればできるだろうか。