我如何在方案中创建函数apply? 一个my-apply函数,与它做同样的事情。
(define (my-apply fn lst)
(if (null? lst)
我不确定从哪里开始或如何开始。
答案 0 :(得分:3)
我认为apply
是"更基本的"比eval
,所以以下是作弊:
(define (my-apply func args)
(eval `(,func ,@args)))
我认为你可以在没有eval
的情况下做到这一点。
答案 1 :(得分:1)
我前段时间创建了一个lisp解释器,它有eval
和宏,但它没有apply
。我想知道是否有办法让我的翻译支持apply
,所以努力尝试这个。这是我的第一次尝试:
(define (my-apply proc args)
(eval (cons proc args)))
这显然不起作用,因为函数和参数列表被评估两次。例如。 (my-apply cons '(a b))
会向您(cons a b)
而不是(cons 'a 'b)
。然后我认为这可能是一个宏的工作,但抛弃了这个想法,因为在宏扩展时不知道参数列表。它需要的程序是这样我虽然我可以在将它传递给eval
之前引用该列表。
(define (my-apply proc args)
(define (q v)
(list 'quote v))
(eval (cons proc (map q args))))
这实际上有效,但这比原生apply
撤消作业eval
所做的工作要多得多。
如果您不被允许使用eval
,那你真的不走运。它无法完成。在不使用eval
的情况下实现apply
也是如此,因为那时你无法做基元。
答案 2 :(得分:0)
(define (my-two-arg-apply f a)
(let ((l (length a)))
(cond ((= l 0) (f))
((= l 1) (f (car a)))
((= l 2) (f (car a) (cadr a))
...
((= l 5) (f (car a) (cadr a) ... (caddddr a)))
...
((= l 7) (f (car a) (cadr a) ... (caddddr a)
(list-ref a 5) (list-ref a 6)))
... ;; lots more cases
(else (error "argument passing limit exceeded")))))
可以使用宏来生成所需的大量代码。
在R6RS中引入了 error
。令人惊讶的是,Scheme计划没有合理的方法在此之前报告错误。
甚至不要考虑制作pop
宏并使用模式(f (pop a) (pop a) ... (pop a))
;与其他一些Lisp方言(如ANSI CL)不同,Scheme没有为函数参数定义的评估顺序。