【问题标题】:How to implement append procedure using tail recursion in Scheme/Racket? [duplicate]如何在 Scheme/Racket 中使用尾递归实现附加过程? [复制]
【发布时间】:2020-11-14 14:19:06
【问题描述】:

长期以来,我一直在尝试使用尾递归(迭代)在 Racket 中实现附加过程。

到目前为止我做的最好的解决方案是:

(define (my-reverse lst)
  (define (iter lst reversed)
    (if (null? lst)
        reversed
        (iter (cdr lst) (cons (car lst) reversed))))
  (iter lst '()))

(define (append-iter el lst)
  (my-reverse (cons el (my-reverse lst))))

(append-iter 4 '(1 2 3)) ; (1 2 3 4)

我的问题是是否有更好的实现方式?

【问题讨论】:

  • 有趣的是,奥斯卡和威尔似乎忘记了他们在 8 年前为同一个问题写过答案
  • 请链接。 :) 啊,傻瓜。谢谢!如果现在的答案也和当时一样,那将是最有趣的......@Sylwester
  • @Sylwester 啊,是的,我记得那个。不过,它对解决方案还有一个要求,即“功能性”。这个我更多地认为是对问题中OP代码的评论请求,如何改进它。所以我想我会推荐我对 dup 的回答为“更好的方法”。 :)

标签: recursion functional-programming scheme racket tail-recursion


【解决方案1】:

嗯,这取决于你对“更好”的定义:)。您的解决方案很简单,而且您找不到更直接的方法来编写自己的过程以使用尾递归将元素附加到列表的末尾。

我唯一的评论是 my-reverse 与内置的 reverse 过程相同,它肯定是尾递归的,所以你可以简单地写成:

(define (append-iter el lst)
  (reverse (cons el (reverse lst))))

如果您可以使用continuation passing style,以下解决方案也是尾递归的,它只取决于最基本的原始过程:

(define (append-iter el lst)
  (append-cps lst (cons el '()) (lambda (x) x)))

(define (append-cps lst1 lst2 k)
  (if (null? lst1)
      (k lst2)
      (append-cps
       (cdr lst1)
       lst2
       (lambda (appended-cdr)
         (k (cons (car lst1) appended-cdr))))))

无论哪种方式,它都按预期工作:

(append-iter 4 '(1 2 3))
=> '(1 2 3 4)

如果您很好奇,CPS 解决方案将评估为如下所示的表达式,这自然会导致答案:

((lambda (append-cdr)
   ((lambda (appended-cdr)
      ((lambda (appended-cdr)
         ((lambda (x) x)
          (cons 1 appended-cdr)))
       (cons 2 appended-cdr)))
    (cons 3 append-cdr)))
 '(4))
=> '(1 2 3 4)

【讨论】:

    【解决方案2】:

    是的,

    (define (rev-append lst reversed)
        (if (null? lst)
            reversed
            (rev-append (cdr lst) 
                        (cons (car lst) reversed))))
    
    (define (append-iter el lst)
      (rev-append (rev-append lst '()) 
                  (cons el '())))
    

    稍微“更好”。

    rev-append 是您的my-reverseiter。它值得拥有自己的顶级绑定。

    【讨论】:

      猜你喜欢
      • 2023-04-01
      • 1970-01-01
      • 2019-07-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-10
      • 2019-04-07
      相关资源
      最近更新 更多