如何根据传入的变量调用特定函数?

时间:2009-09-01 10:38:10

标签: common-lisp

我对lisp相当新,但我一直在玩它。我有几个问题需要澄清。下面是我定义的小宏。

(defmacro transform (query)
 '(lambda (row)
   (eq (nth 1 query) (nth 0 (nth 0 row)))
  )
)

我只是想知道如何动态指定在身体中使用的功能?如果我想使用“+”或“ - ”函数而不是“eq”,或者甚至是我定义的另一个函数?就像我认为可以将函数的名称作为参数传递但显然不起作用。当我修改传入的列表(查询)时,我也会收到变量未绑定错误。

2 个答案:

答案 0 :(得分:2)

在宏的主体中,您可以使用所有Lisp的运行时库来生成实际的扩展。所以,例如:

(defmacro transform (query &key (test 'eq))
   (let ((row-var (gensym)))
     `(lambda (,row-var) 
        (,test (nth 1 ,query) (nth 0 (nth 0 ,row-var))))))

此版本使用“反引号”而不是普通撇号,它允许在主体内“取消引用”表单,从而允许将生成的表单包含在结果中。

您可以像原始版本一样使用此宏:

(transform (...))

或(传递显式测试函数):

(transform (...) :test equal)

请注意,您不应在宏扩展中使用普通符号作为变量名称(作为生成的 lambda 表达式的参数),因为这可能会意外干扰在使用宏的网站上使用该符号。您只是不知道何时编写宏,在使用宏时是否会在某处使用名为 row 的变量,以及它是否已在查询中使用形式/表达。您的原始定义将“捕获”变量,可能会改变查询所做的含义。

答案 1 :(得分:0)

funcall就是答案!决定只传入它并使用funcall来评估函数。