在运行时按名称调用函数

时间:2011-02-07 22:47:25

标签: lisp common-lisp

我意识到可以使用#'PRINT引用函数来引用PRINT函数。如果我们有一个列表S,其中第一个元素是'PRINT,我们可以使用#(car S)来引用它吗?

我说我正在查看列表中的元素是原子,这些原子是某些函数的名称。目前,我可以这样做:

(defun aritheval (S)
    (funcall
        (cond
            ((eq '+ (car S)) #'+)
            ((eq '- (car S)) #'-)
            ((eq '* (car S)) #'*)
            ((eq '/ (car S)) #'/)
        )
        '2
        '3
    )
)

此函数将计算2 + 3,2-3,2 * 3或2/3,具体取决于列表S中的第一个元素.S包含这些函数的名称。

1 个答案:

答案 0 :(得分:6)

#(车S)毫无意义。语法存在但是表示带符号CAR和S的向量。

使用

(funcall (first somelist) someargument)

(apply (first somelist) a-list-of-arguments)

您的功能是非Lispy格式的。

在正确的Lisp代码中不使用尾随括号。您也不需要引用数字。数字是自我评估的,他们对自己进行评估。此外,我们现在可能更喜欢FIRST over CAR和REST over CDR。功能相同,但名称更好。每当我们处理简单列表时,都会使用FIRST,SECOND,THIRD,......和REST。

(defun aritheval (S)
  (funcall (cond ((eq '+ (car S)) #'+)
                 ((eq '- (car S)) #'-)
                 ((eq '* (car S)) #'*)
                 ((eq '/ (car S)) #'/))
            2 3)))

由于符号可以用作全局函数的名称,因此不需要上面的内容。

考虑到符号到函数的映射是相同的,下面的函数也是如此。

(defun aritheval (s)
  (funcall (first s) 2 3)))