繁体   English   中英

如何在Racket上订购我的累积变量?

[英]How to order my accumulate variable in this case on Racket?

出于教育原因,我正在使用Racket进行编码。

我被赋予了一个任务,我应该在其中创建一个函数,在没有过滤器的情况下,将接收列表作为输入,并返回另一个列表,仅使用第一个列表的偶数。

我想出了迭代过程的这种递归定义:

(define (add-even lista)
  (define (iter lista accu)
    (cond ((null? lista) accu)
          ((even? (car lista)) (iter (cdr lista)
                                     (cons (car lista) accu)))
          (else (iter (cdr lista) accu))))
  (iter lista empty))

它工作正常。 但是,我以相反的顺序得到结果,例如:

(add-even '(1 2 3 4 5 6 7))
>> '(6 4 2)

如何在输入上以相同的外观顺序输出?

我知道如何使用反向功能。 但这不是一种非常有效的方式..

当然你可以不用iter程序就可以做到......

(define (add-even lista)
  (cond ((null? lista) empty)
        ((even? (car lista)) (cons (car lista) (add-even (cdr lista))))
        (else (add-even (cdr lista)))))

(add-even '(1 2 3 4 5 6 7))
; => '(2 4 6)

但我假设你正在使用它来保持你的add-even过程的尾递归。 如果是这样的话......


你的accu可以是一个程序 (而不是一个列表),它填补了你的cons链中的“漏洞”。 您可以填写最后一个值,而不是在计算结束时返回accu ,在这种情况下,该值为empty并使用identity初始化。

我使用粗体来显示我更改的代码部分

(define (add-even lista)
  (define (iter lista accu)
    (cond ((null? lista) (accu empty))
          ((even? (car lista)) (iter (cdr lista)
                                     (λ (rest) (accu (cons (car lista) rest)))))
          (else (iter (cdr lista) accu))))
  (iter lista identity))

(add-even '(1 2 3 4 5 6 7))
; => '(2 4 6)

所以现在你得到尾递归,然后按正向顺序构建列表。 我鼓励你通过对此的评估来看看它是如何工作的。 这是继续传递风格


如果你稍微重命名变量,也许程序会更好

(define (add-even lista)
  (define (iter l k)
    (cond ((null? l) (k empty))
          ((even? (car l)) (iter (cdr l)
                                 (λ (rest) (k (cons (car l) rest)))))
          (else (iter (cdr l) k))))
  (iter lista identity))

(add-even '(1 2 3 4 5 6 7))
; => '(2 4 6)

如果你使用了一个named-let ,它甚至可以清理一点

(define (add-even lista)
  (let iter [(l lista) (k identity)]
    (cond ((null? l) (k empty))
          ((even? (car l)) (iter (cdr l)
                                 (λ (rest) (k (cons (car l) rest)))))
          (else (iter (cdr l) k)))))

(add-even '(1 2 3 4 5 6 7))
; => '(2 4 6)

...它清理,如果我们用 composecurry

(define (add-even lista)
  (let iter [(l lista) (k identity)]
    (cond ((null? l) (k empty))
          ((even? (car l)) (iter (cdr l) (compose k (curry cons (car l)))))
          (else (iter (cdr l) k)))))

(add-even '(1 2 3 4 5 6 7))
; => '(2 4 6)

在Racket中,内置for/list with #:when子句也可用于创建一个短函数:

(define (onlyeven lst)
  (for/list ((i lst) #:when (even? i))
    i))

(onlyeven '(1 2 3 4 5 6 7))
; => '(2 4 6)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM