如何通过符号或字符串调用flet函数?
((lambda (s) (flet ((fn1 (x) x)) (funcall s))) 'fn1)
和
((lambda (s) (flet ((fn1 (x) x)) (funcall s))) "fn1")
我知道上面的代码不起作用,因为funcall需要一个符号,但是我不知道如何在flet或let内部创建该符号。
没有从符号到词法绑定函数的默认映射。 Common Lisp不提供此功能。
一个需要做的事情:
CL-USER 212 > ((lambda (s arg)
(flet ((fn1 (x) x))
(case s
(fn1 (fn1 arg)))))
'fn1
42)
42
根据我的经验,由flet
和labels
创建的内部函数的名称只对定义函数无关紧要:
(defun create-adder (x)
(flet ((add (y) (+ x y)))
;; only this function CREATE-ADDER needs to know
;; that the flet is named ADD.
#'add))
(setq f (create-adder 3))
> #<Interpreted Closure (flet create-adder add) @ #x100208cf302>
将flet称为add
没关系。重要的是它是一个功能(关闭),您可以funcall
:
(funcall f 2)
> 5
您可以基于参数创建其他闭包:
(defun create-adder (kind)
(flet ((add-1 (x) (+ x 1))
(add-2 (x) (+ x 2)))
(ecase kind
(1 #'add-1)
(2 #'add-2))))
(create-adder 1)
> #<Interpreted Closure (flet create-adder add-1) @ #x10020903c52>
(create-adder 2)
> #<Interpreted Closure (flet create-adder add-2) @ #x10020902862>
如何通过符号或字符串调用flet函数?
您不能; flet函数是词汇绑定,而不是符号和函数之间的动态关联。 flet函数绑定由符号命名,但是该关联不在全局环境中,并且在编译代码时可能会消失。
如果我们有这样的功能:
(lambda (s) (flet ((fn1 (x) x)) (funcall s)))
内部fn1
是隐藏的,封装的实现细节,局外人不应该知道。
最好以这种方式对待,并考虑一个不需要调用者知道fn1
的解决方案。
分派内部函数的匿名函数似乎是反模式;我们可以捕获多个lambda:
(let (v1 v2 ...)
(flet ((fn1 (x) ...) (fn2 (x) ...))
(vector #'fn1 #'fn2)))
现在如果要调用fn2
,我们将返回的向量和(funcall (aref vec 1) arg)
。该向量本身将调度机制提供给共享相同捕获词法环境的多个操作。
[我们正在做的是以一种不好的方式重塑OOP;我们可能应该使用结构或对象。