【问题标题】:How to recreate apply in scheme如何在方案中重新创建应用
【发布时间】:2017-04-13 16:24:00
【问题描述】:

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

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

我不知道从这里去哪里或如何开始。

【问题讨论】:

  • 你可以使用什么?
  • 所有纯函数构造,以及映射,因为我已经实现了
  • 如果你可以使用eval,任务很简单;-)
  • 我觉得我做不到 :(
  • 那我觉得你不能实现apply

标签: function recursion scheme lisp apply


【解决方案1】:

我认为applyeval“更基础”,所以下面是作弊:

(define (my-apply func args)
  (eval `(,func ,@args)))

如果没有eval,我认为你做不到。

【讨论】:

    【解决方案2】:

    不久前我创建了一个 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,那你就真的不走运了。这是不可能的。在不使用apply 的情况下实现eval 也是如此,从那时起你就无法使用原语。

    【讨论】:

      【解决方案3】:
      (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")))))
      

      宏可用于生成所需的大量代码。

      error 在 R6RS 中被引入。令人惊讶的是,在此之前,Scheme 程序没有合理的方法来报告错误。

      甚至不要考虑制作pop 宏并使用(f (pop a) (pop a) ... (pop a)) 模式;与 ANSI CL 等其他 Lisp 方言不同,Scheme 没有定义函数参数的评估顺序。

      【讨论】:

        猜你喜欢
        • 2021-11-17
        • 1970-01-01
        • 2014-10-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多