在这种情况下如何在球拍上订购我的累积变量?
How to order my accumulate variable in this case on Racket?
出于教育原因,我正在使用 Racket 进行编码。
我得到了一个任务,我应该创建一个函数,在没有过滤器的情况下,它将接收一个列表作为输入,return另一个列表只包含第一个列表的偶数。
我想到了迭代过程的递归定义:
(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
链中填充 "hole"。您不必在计算结束时返回 accu
,而是填写最后一个值,在本例中为 empty
并使用 identity
进行初始化。
我使用 粗体 来显示我更改的代码部分
(define (add-even lista)
(define (iter lista accu)
(cond ((null? lista) <b>(accu empty)</b>)
((even? (car lista)) (iter (cdr lista)
<b>(λ (rest) (accu </b>(cons (car lista) <b>rest))</b>)))
(else (iter (cdr lista) accu))))
(iter lista <b>identity</b>))
(add-even '(1 2 3 4 5 6 7))
; => '(2 4 6)
所以现在你得到了尾递归并且你以正向顺序构建列表。我鼓励您逐步完成对此的评估,看看它是如何工作的。这是continuation passing style.
如果您稍微重命名变量,也许程序会更好
(define (add-even lista)
(define (iter <b>l</b> <b>k</b>)
(cond ((null? <b>l</b>) (<b>k</b> empty))
((even? (car <b>l</b>)) (iter (cdr <b>l</b>)
(λ (rest) (<b>k</b> (cons (car <b>l</b>) rest)))))
(else (iter (cdr <b>l</b>) <b>k</b>))))
(iter lista identity))
(add-even '(1 2 3 4 5 6 7))
; => '(2 4 6)
如果你使用 named-let
,它会更干净一点
(define (add-even lista)
(<b>let</b> iter [<b>(l lista)</b> <b>(k identity)</b>]
(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)
... 如果我们使用 compose
和 curry
,它甚至可以清理 更多
(define (add-even lista)
(let iter [(l lista) (k identity)]
(cond ((null? l) (k empty))
((even? (car l)) (iter (cdr l) (<b>compose</b> k (<b>curry</b> 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)
出于教育原因,我正在使用 Racket 进行编码。
我得到了一个任务,我应该创建一个函数,在没有过滤器的情况下,它将接收一个列表作为输入,return另一个列表只包含第一个列表的偶数。
我想到了迭代过程的递归定义:
(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
链中填充 "hole"。您不必在计算结束时返回 accu
,而是填写最后一个值,在本例中为 empty
并使用 identity
进行初始化。
我使用 粗体 来显示我更改的代码部分
(define (add-even lista)
(define (iter lista accu)
(cond ((null? lista) <b>(accu empty)</b>)
((even? (car lista)) (iter (cdr lista)
<b>(λ (rest) (accu </b>(cons (car lista) <b>rest))</b>)))
(else (iter (cdr lista) accu))))
(iter lista <b>identity</b>))
(add-even '(1 2 3 4 5 6 7))
; => '(2 4 6)
所以现在你得到了尾递归并且你以正向顺序构建列表。我鼓励您逐步完成对此的评估,看看它是如何工作的。这是continuation passing style.
如果您稍微重命名变量,也许程序会更好
(define (add-even lista)
(define (iter <b>l</b> <b>k</b>)
(cond ((null? <b>l</b>) (<b>k</b> empty))
((even? (car <b>l</b>)) (iter (cdr <b>l</b>)
(λ (rest) (<b>k</b> (cons (car <b>l</b>) rest)))))
(else (iter (cdr <b>l</b>) <b>k</b>))))
(iter lista identity))
(add-even '(1 2 3 4 5 6 7))
; => '(2 4 6)
如果你使用 named-let
(define (add-even lista)
(<b>let</b> iter [<b>(l lista)</b> <b>(k identity)</b>]
(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)
... 如果我们使用 compose
和 curry
(define (add-even lista)
(let iter [(l lista) (k identity)]
(cond ((null? l) (k empty))
((even? (car l)) (iter (cdr l) (<b>compose</b> k (<b>curry</b> 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)