[英]How to order my accumulate variable in this case on Racket?
I am coding with Racket for educational reasons. 出于教育原因,我正在使用Racket进行编码。
I was given a task in which I should create a function that, without filter, would receive a list as an input and return another list only with the even numbers of the first list. 我被赋予了一个任务,我应该在其中创建一个函数,在没有过滤器的情况下,将接收列表作为输入,并返回另一个列表,仅使用第一个列表的偶数。
I came up with this recursive definition of an iterative process: 我想出了迭代过程的这种递归定义:
(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))
It works fine. 它工作正常。 However, I get the result in a reverse order, eg:
但是,我以相反的顺序得到结果,例如:
(add-even '(1 2 3 4 5 6 7))
>> '(6 4 2)
What should I do to have the output in the same order of appearance on the input? 如何在输入上以相同的外观顺序输出?
I know how to do it with a reverse function. 我知道如何使用反向功能。 But that's not a very efficient way..
但这不是一种非常有效的方式..
Of course you can do it without the iter
procedure ... 当然你可以不用
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)
But I assume you're using that to keep your add-even
procedure tail-recursive. 但我假设你正在使用它来保持你的
add-even
过程的尾递归。 If that's the case then ... 如果是这样的话......
Your accu
can be a procedure (instead of a list) which fills in a "hole" in your cons
chain. 你的
accu
可以是一个程序 (而不是一个列表),它填补了你的cons
链中的“漏洞”。 Instead of returning accu
at the end of the computation, you fill in the last value, which in this case is empty
and initialize with identity
instead. 您可以填写最后一个值,而不是在计算结束时返回
accu
,在这种情况下,该值为empty
并使用identity
初始化。
I used bolding to show the parts of your code I changed 我使用粗体来显示我更改的代码部分
(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)
So now you get tail-recursion and you build the list in forward order. 所以现在你得到尾递归,然后按正向顺序构建列表。 I encourage you to step thru the evaluation of this to see how it works.
我鼓励你通过对此的评估来看看它是如何工作的。 This is continuation passing style .
这是继续传递风格 。
And perhaps the procedure would be better if you renamed the vars a little bit 如果你稍微重命名变量,也许程序会更好
(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)
And it cleans up even a little more if you used a named-let
如果你使用了一个
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)
... And it cleans up even more if we used compose
and curry
...它清理,如果我们用更
compose
和curry
(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)
In Racket, built-in for/list
with #:when
clause can also be used to create a short function: 在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.