簡體   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