当我在函数中使用 eval
之类的东西时,我试图了解数据与代码替换是如何工作的,该函数允许我传递任何打印命令,例如 print
princ
等和一些文本,它在输出中使用该命令:
(defun print-test (fn text)
(eval '(fn 'text)))
我尝试了各种方法,但无法运行它。我也试过:
(defun print-test (fn text)
(eval ('fn 'text)))
..和其他变化。所以我显然错过了一些东西。我希望能够做到这一点:
(print-test 'princ'some-text)
我通常会收到错误消息 fn is undefined
。但是由于我实时评估代码,我认为它可以从我的输入中获取 fn
?
我意识到还有其他方法可以做到这一点,比如传入一个像 #'princ
这样的实际函数对象,但我很好奇 eval
机制如何用于生成即时代码。
最佳答案
fn is undefined
之类的错误并不是告诉您 princ
未定义,而是符号 fn
没有函数绑定(bind)。你不想调用符号 fn
,你想调用变量 fn
的 value。
您似乎想要评估一个列表,该列表的第一个元素是 fn
的值,第二个元素是 text
的值。您将使用 (list fn text)
中的函数 list
创建这样一个列表。然后你可以用它调用 eval
:
(defun print-test (fn text)
(eval (list fn text)))
你也可以使用反引号,然后做
(defun print-test (fn text)
(eval `(,fn ,text)))
在这些情况下,如果你想和(princ 'hi)
有同样的效果,你需要fn
为符号princ
和 text
成为 list 'hi
(是的,列表,因为 'hi
是 (引用你好)
)。你会这样调用,然后:
(print-test 'princ ''hi)
如果第二个参数应该总是在生成的文本中被引用,您也可以使用以下任何一种:
(eval `(,fn ',text))
(eval `(,fn (quote ,text)))
(eval (list fn (list 'quote text)))
尽管如此,这似乎是一种使用 eval
的非常奇怪的方式。除非有一些特别好的理由,否则为什么不直接使用 funcall
?毕竟,如果 fn
作为要评估的表单的汽车是合法的,并且 text
是一个参数,那么这不能简单地是以下内容吗?
(defun print-test (fn text)
(funcall fn text))
当然,这会被称为有点不同。在这里,如果您想要与 (princ 'hi)
相同的效果,您只需传递符号 princ
和 hi
:
(print-test 'princ 'hi)
关于lisp - eval 如何以这种方式处理函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19994681/