![](/img/trans.png)
[英]Reverse a list with foldr and foldl using the same auxiliary functions
[英]Reverse a list in Scheme with foldl and foldr
如何使用foldr
和foldl
定義在Scheme中反轉列表的函數?
我們想要的是一個簡潔的解決方案,該方案使用foldl
調用來反轉Scheme中的列表,並使用定義的foldr
調用來解決另一個問題:
(define (foldl operation lst initial)
(if (null? lst) initial
(foldl operation
(cdr lst)
(operation (car lst) initial))))
和
(define (foldr operation lst initial)
(if (null? lst) initial
(operation
(car lst)
(foldr operation (cdr lst) initial))))
精明的人會發現foldl
實現是尾遞歸的,因為返回值是在調用每個遞歸步驟時計算的-在最后一步,整個答案已經計算出來,並簡單地在鏈上返回。
foldr
實現不是尾遞歸的,因為它必須使用返回到遞歸鏈上的值來構建返回的值。
因此,我們感興趣的兩個Scheme實現應采用以下形式:
(define (rev1 lst)
(foldl ___________________________
**Solution:**
(define (rev1 lst)
(foldl cons lst '()))
和
(define (rev2 lst)
(foldr ___________________________
**Solution 1:**
(define (rev2 lst)
(foldr
(lambda (element accumulator)
(foldr cons accumulator (cons element '())))
lst '()))
**Solution 2:**
(define (rev2 lst)
(foldr
(lambda (element accumulator)
(append accumulator (cons element '())))
lst '()))
最終目標是能夠調用以下命令,
(rev1 '(1 2 3)) -> (3 2 1)
(rev2 '(1 2 3)) -> (3 2 1)
foldl
解決方案應該相對瑣碎(根據我們的直覺),但是foldr
解決方案可能需要更多的思考。
先前與此問題類似(但文獻記載少得多)的問題卻未得到回答和/或結束。
這看起來像是作業,所以我會給您一些提示以幫助您入門。 foldl
情況很簡單,您只需要發現要傳遞的正確函數,並記住: foldl
可以可視化為向后處理列表(最后一個元素在前,最后一個元素在后),所以您要做的就是將當前列表中具有累計值的元素:
(define (rev1 lst)
(foldl <???> lst '()))
文件foldr
情況只是稍微困難一點,只記得文件foldr
會按照在輸入列表中出現的順序處理列表中的元素。 同樣,您必須找到正確的過程來調用:
(define (rev2 lst)
(foldr (lambda (e a)
<???>)
lst
'()))
您需要以某種方式將e
(當前元素)放在累積值a
的末尾 。 提示:您會發現append
和list
在這里很有用。
您的rev1
'解決方案'無法編譯...如果您將list
替換為l
> (define (rev1 l)
(foldl cons l '()))
> (rev1 '(1 2 3))
(3 2 1)
對於您的rev2
它可以作為主體:
> (foldr (lambda (a b) (append b (list a))) '(1 2 3) '())
(3 2 1)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.