2013-03-21 79 views
4

我正在学习球拍(类似Lisp的计划),并且我试图做类似(apply + '(1 2))但没有使用apply,我失败了。我几乎可以肯定的是,apply可以用eval以某种方式模拟,但现在我有疑惑。是否可以使用`eval`在Lisp中实现`apply`?

所以,我的问题是:可以在Racket(或其他Lisp)中使用eval和其他基本操作来实现apply?也就是说,如何使这项工作:

{ define [my-apply f arg] 
    ;; what does go here? 
} 
(my-apply + (list 1 2)) ; => 3 
+0

当然可以。提示:诀窍是将functor和arg列表传递给'eval'而不用自己评估列表,所以你需要使用'(list ...)'和'(quote ...)'。 – 2013-03-21 14:42:17

+1

如果'arg'引用词法范围变量,是否有解决方案? – finnw 2013-03-21 15:45:36

+1

你必须考虑的是eval调用适用。因此,如果您通过调用eval来定义my-apply,然后调用eval,那么您是否确实在不使用apply的情况下定义了my-apply? – WuHoUnited 2013-03-21 15:54:09

回答

2

当然。

(defun my-apply (function arglist) 
    (eval (cons function (mapcar (lambda (x) (list 'quote x)) arglist)))) 
(my-apply '+ '(1 2 3)) 
6 
(my-apply '+ '(1 a 3)) 
*** - +: A is not a number 
  1. 请注意,你不能这样做(my-apply #'+ '(1 2 3)),这将需要额外的步骤。

  2. 请注意,您必须引用arglist元素,以避免双重评价(感谢瑞安用来捕获!)

+3

(eval(list *'funcall(list'quote function)arglist)) – 2013-03-21 15:56:33

+0

@RainerJoswig:我也想避免'funcall' – sds 2013-03-21 15:59:43

+0

'(my-apply'+'((recursively-delete-all-文件“/”)))'? – 2013-03-21 21:00:51

0

我发现这个(球拍):

{ define [my-apply func args] 
    { define ns-for-eval (make-base-namespace) } 
    (eval (cons func args) ns-for-eval) 
} 

(my-apply + (list 1 2)) ; => 3 

它有什么问题吗?

+0

我发现自己评估的参数元素存在问题。我可能会在元素方面引用args,就像在sds的答案中一样,但它看起来太复杂了。 – Alexey 2013-03-26 20:31:56

相关问题