如何通过符号或字符串调用flet函数?

问题描述 投票:0回答:3

如何通过符号或字符串调用flet函数?

((lambda (s) (flet ((fn1 (x) x)) (funcall s))) 'fn1)

((lambda (s) (flet ((fn1 (x) x)) (funcall s))) "fn1")

我知道上面的代码不起作用,因为funcall需要一个符号,但是我不知道如何在flet或let内部创建该符号。

lisp common-lisp
3个回答
2
投票

没有从符号到词法绑定函数的默认映射。 Common Lisp不提供此功能。

一个需要做的事情:

CL-USER 212 > ((lambda (s arg)
                 (flet ((fn1 (x) x))
                   (case s
                     (fn1 (fn1 arg)))))

               'fn1
               42)
42

1
投票

根据我的经验,由fletlabels创建的内部函数的名称只对定义函数无关紧要:

(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>

0
投票

如何通过符号或字符串调用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;我们可能应该使用结构或对象。

© www.soinside.com 2019 - 2024. All rights reserved.