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

Lisp eval如何以这种方式处理函数,lisp,common-lisp,Lisp,Common Lisp,我试图了解在函数中使用类似于eval的东西时,数据与代码替换是如何工作的,该函数允许我传入任何打印命令,如printprinc等,以及一些文本,并在输出中使用该命令: (defun print-test (fn text) (eval '(fn 'text))) 我尝试过各种方法,但都无法运行。我还尝试: (defun print-test (fn text) (eval ('fn 'text))) …和其他变体。所以我显然错过了一些东西。我希望能够做到这一点: (打印测试“原则”某

我试图了解在函数中使用类似于
eval
的东西时,数据与代码替换是如何工作的,该函数允许我传入任何打印命令,如
print
princ
等,以及一些文本,并在输出中使用该命令:

(defun print-test (fn text)
  (eval '(fn 'text)))
我尝试过各种方法,但都无法运行。我还尝试:

(defun print-test (fn text)
  (eval ('fn 'text)))
…和其他变体。所以我显然错过了一些东西。我希望能够做到这一点:

(打印测试“原则”某些文本)

我通常会得到一个错误
fn未定义
。但由于我在实时评估代码,我认为它可以从我的输入中获得
fn


我意识到还有其他方法可以做到这一点,比如传入一个实际的函数对象,比如
#princ
,但我很好奇
eval
机制如何在运行中生成代码。

一个错误,比如
fn是未定义的
并没有告诉您
princ
是未定义的,但是符号
fn
没有函数绑定。您不想调用符号
fn
,而是想调用变量
fn
的值

看起来您想要计算一个列表,该列表的第一个元素是
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
作为列表
'hi
(是的,列表,因为
'hi
(quote hi)
)的缩写)。你会这样打电话,然后:

(print-test 'princ ''hi)
如果生成的文本中应始终引用第二个参数,则您也可以使用以下任一选项:

(eval `(,fn ',text))
(eval `(,fn (quote ,text)))
(eval (list fn (list 'quote text)))
尽管如此,使用
eval
似乎是一种非常奇怪的方式。除非有特别好的理由,为什么不直接使用
funcall
?毕竟,如果
fn
作为评估表单的car是合法的,而
text
是一个参数,那么这难道不能简单地如下所示吗

(defun print-test (fn text)
  (funcall fn text))
当然,这个名字会有点不同。在这里,如果您想要与
(princ'hi)
相同的效果,只需传递符号
princ
hi

(print-test 'princ 'hi)

fn未定义
这样的错误不会告诉您
princ
未定义,而是告诉您符号
fn
没有函数绑定。您不想调用符号
fn
,而是想调用变量
fn
的值

看起来您想要计算一个列表,该列表的第一个元素是
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
作为列表
'hi
(是的,列表,因为
'hi
(quote hi)
)的缩写)。你会这样打电话,然后:

(print-test 'princ ''hi)
如果生成的文本中应始终引用第二个参数,则您也可以使用以下任一选项:

(eval `(,fn ',text))
(eval `(,fn (quote ,text)))
(eval (list fn (list 'quote text)))
尽管如此,使用
eval
似乎是一种非常奇怪的方式。除非有特别好的理由,为什么不直接使用
funcall
?毕竟,如果
fn
作为评估表单的car是合法的,而
text
是一个参数,那么这难道不能简单地如下所示吗

(defun print-test (fn text)
  (funcall fn text))
当然,这个名字会有点不同。在这里,如果您想要与
(princ'hi)
相同的效果,只需传递符号
princ
hi

(print-test 'princ 'hi)

fn未定义
这样的错误不会告诉您
princ
未定义,而是告诉您符号
fn
没有函数绑定。您不想调用符号
fn
,而是想调用变量
fn
的值

看起来您想要计算一个列表,该列表的第一个元素是
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
作为列表
'hi
(是的,列表,因为
'hi
(quote hi)
)的缩写)。你会这样打电话,然后:

(print-test 'princ ''hi)
如果生成的文本中应始终引用第二个参数,则您也可以使用以下任一选项:

(eval `(,fn ',text))
(eval `(,fn (quote ,text)))
(eval (list fn (list 'quote text)))
尽管如此,使用
eval
似乎是一种非常奇怪的方式。除非有特别好的理由,为什么不直接使用
funcall
?毕竟,如果
fn
作为评估表单的car是合法的,而
text
是一个参数,那么这难道不能简单地如下所示吗

(defun print-test (fn text)
  (funcall fn text))
当然,这个名字会有点不同。在这里,如果您想要与
(princ'hi)
相同的效果,只需传递符号
princ
hi

(print-test 'princ 'hi)

fn未定义
这样的错误不会告诉您
princ
未定义,而是告诉您符号
fn
没有函数绑定。您不想调用符号
fn