如何将lambda传递给宏?

时间:2015-10-15 19:53:56

标签: lambda lisp common-lisp

我需要传递函数并使用指定的参数调用它。如何正确地将lambda函数传递给宏并避免此错误:

  

申请:#'(LAMBDA(X)(+ X 1))不是函数名称;尝试使用符号

代码:

(defmacro runner (fun &rest arg)
  (apply fun arg))

呼叫:

(runner #'(lambda (x) (+ x 1)) '(1))

我的代码出了什么问题?尝试使用+函数类似的东西,一切正常。

更新: 程序应该为每个参数调用指定的函数并返回结果。参数是列表。所以我应该通过不同的函数列出。

(setq l1 (list 1 2 3))
(setq l2 (list 2 3 4))
(setq l3 (list 3 4 5))

(defmacro runner (fun &rest arg)
  ; some code
)

(defun summer (l)
  (reduce #'+ l))

(print (runner summer l1 l2 l3))

就像这样,但是有任意数量的参数。

(defun runner (l)
   (mapcar #'(lambda (x) (summer x)) l))

(print (runner (list l1 l2 l3)))

1 个答案:

答案 0 :(得分:7)

你需要在宏中使用反引号,所以它在运行时扩展为对函数的调用,而不是编译时。

(defmacro runner (fun &rest arg)
   `(mapcar (lambda (a) (funcall #',fun a)) (list ,@arg)))

(setq l1 (list 1 2 3))
(setq l2 (list 2 3 4))
(setq l3 (list 3 4 5))

(defun summer (l)
  (reduce #'+ l))

(print (runner summer l1 l2 l3))

(print (runner (lambda (x) (+ x 1)) 1 3 4))

由于runner期望第一个参数是函数名,因此它在调用函数之前会添加#'前缀。因此,当您调用它时,不应在lambda之前使用它。

我将apply更改为funcall,因为您调用summer的方式表明您希望每个列表作为单个参数传递,而不是传播。并且因为你的lambda表达式期望它的参数是单个数字而不是列表,所以我将这些数字作为单独的参数传递,而不是包含在列表中。

DEMO