2015-10-15 26 views
1

我需要传递函数并用指定的参数调用它。如何正确地传递lambda函数,以宏观和避免这个错误:如何将lambda传递给宏?

APPLY: #'(LAMBDA (X) (+ X 1)) is not a function name; try using a symbol instead

代码:

(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

你为什么要用宏而不是函数来做这件事?宏在编译时用于扩展代码。 – Barmar

+0

我需要使用语法创建宏(do-this function(list1)(list2)...(listn))并执行诸如mapcar之类的操作,但使用列表并返回新值。 – solomkinmv

回答

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

+0

我认为你最后defmacro被认为是一个defun – PuercoPop

+0

好的。但是我仍然无法使用宏来评估所有参数的指定函数:( – solomkinmv

+0

)请更新这个问题的实际内容,如果给出多个参数,请显示它应该展开的内容 – Barmar