如何在方案中重新申请

时间:2017-04-13 16:24:01

标签: function recursion scheme lisp apply

我如何在方案中创建函数apply? 一个my-apply函数,与它做同样的事情。

 (define (my-apply fn lst)
 (if (null? lst)

我不确定从哪里开始或如何开始。

3 个答案:

答案 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没有为函数参数定义的评估顺序。