如何在这种情况下在球拍上订购我的累积变量? [英] How to order my accumulate variable in this case on Racket?

查看:117
本文介绍了如何在这种情况下在球拍上订购我的累积变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我得到了一个任务,我应该创建一个函数,在没有过滤器的情况下,会收到一个列表作为输入并返回另一个列表,只用第一个列表的偶数。



我提出了迭代过程的递归定义:

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

它可以正常工作。然而,我得到了相反的结果,例如:

))
>> '(6 4 2)

我应该怎样才能以相同的外观顺序输出输入?



我知道如何用反向函数来完成它。但这不是一个非常有效的方式。

解决方案

当然,您可以在 iter procedure ...

 (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 ,而应填写最后一个值,在本例中为并使用 identity 进行初始化。



我使用粗体来显示您的部分代码我改变了

$ $ p $ $ $ $ $ $ $ $ $ $ $ $ $ $ (cond((null?lista)(accu empty)
((even?(car lista))(iter(cdr lista)
<λ> )()()()()()()()()()()()() )

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

所以现在你得到尾递归,并且按照前向顺序构建列表。我鼓励你通过对此的评估来了解它是如何工作的。这是延续传球风格

 $ b 

如果您将变量重新命名一次, $ c $(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 ($)

(add-even'(1 2 3 4 5 6 7))
(iter lista identity))
$ b $ )
; =>'(2 4 6)






如果您使用 named-let

 (define(add -even lista)
let iter [(l lista) (k identity)]
(cond(( ()()()()()()()()()()() )
(else(iter(cdr l)k))))
$ b $(add-even'(1 2 3 4 5 6 7))
; =>'(2 4 6)






...并清除如果我们使用撰写咖喱


,那么即使更多

 (define(add-even lista)
(let iter [(l lista)(k identity)]
(cond((null (carl)(it(car))(it) ))))))
(else(iter(cdr l)k))))

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


I am coding with Racket for educational reasons.

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, e.g.:

(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 ...

(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. 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. 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.

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

(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

(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)

这篇关于如何在这种情况下在球拍上订购我的累积变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆