lisp - eval 如何以这种方式处理函数

标签 lisp common-lisp

当我在函数中使用 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,你想调用变量 fnvalue

您似乎想要评估一个列表,该列表的第一个元素是 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为符号princtext 成为 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) 相同的效果,您只需传递符号 princhi:

(print-test 'princ 'hi)

关于lisp - eval 如何以这种方式处理函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19994681/

相关文章:

lisp - 创建大量的gensym是否合理?

class - 不同的初始化,Common Lisp

lisp - 闭包和动态作用域?

lisp - 学习 Lisp。似乎无法从一个函数中获取值并在另一个函数中使用它

lambda - 如何在保留捕获的变量的同时更改 lambda 中的代码?

lisp - 使用 hunchentoot 我无法生成网页

lisp - 使用 parenscript 设置间隔函数

scheme - MIT Scheme 9.2 中 SICP 中的剩余程序是什么?

macros - 如何建立在宏展开期间处于事件状态的变量绑定(bind)?

rest - Common Lisp 中的具象状态转移 (REST)