2013-04-22 72 views
1

我正在使用DrRacket R5RS學習Scheme。我認爲我已經掌握了這些概念,但是我無法得到這個簡單的遞歸練習。我認爲這是DrRacket中的一個錯誤,但我不確定。Scheme(DrRacket) - cond語句不適用於遞歸

有人可以看到問題,並希望解釋爲什麼我的代碼不起作用?我真的很想學習這個功能語言。

此代碼將產生#T和#F正確:

(define three (lambda (L target1 target2 target3 sum) 
    (cond 
     ((= target1 0) (three L (car L) (cadr L) (caddr L) 0)) 
     ((NULL? L) (= (- sum (+ target1 (+ target2 target3))) (+ target1 (+ target2 target3)))) ; sum minus targets = targets 
     (else (three (cdr L) target1 target2 target3 (+ sum (car L))))  ; return true if branch returns true 
))) 

當我啓動該程序(3「(1 2 3 6)0 0 0 0),則返回#T因爲1+ 2 + 3 = 6。當我用(3'(1 2 3 5)0 0 0 0)啓動程序時,從1 + 2 + 3!= 5開始返回#F。

現在,這是問題所在。我想做多分支遞歸。但是,此代碼每次都會返回#T!因爲我不能讓它返回#F,我不能讓它跳到遞歸的下一個分支。

(define three (lambda (L target1 target2 target3 sum) 
    (cond 
     ((= target1 0) (three L (car L) (cadr L) (caddr L) 0)) 
     ((NULL? L) (= (- sum (+ target1 (+ target2 target3))) (+ target1 (+ target2 target3)))) ; sum minus targets = targets 
     ((three (cdr L) target1 target2 target3 (+ sum (car L))) #T)  ; return true if branch returns true     
     (else 'hit_the_bottom) ; IT NEVER HITS THIS STATEMENT!     
))) 

任何想法?

+1

快速回答:用'(else #f)'替換最後一行,它就會起作用。要看到_why_,請看下面的答案。 – 2013-04-22 02:02:58

回答

3

的解決方案過於複雜,如果你只是想檢查,如果前三個數字的列表中的總和等於第四個數字,一個簡單的非遞歸方法將更好地工作:

(define (three lst) 
    (= (+ (first lst) (second lst) (third lst)) 
    (fourth lst))) 

其他那麼,爲什麼不堅持第一種方法呢?它適用於你,不清楚你的意思是「多分支遞歸」,爲什麼它需要第二種方法 - 不是第一種方法「多分支」?畢竟它已經遞歸調用了three兩個部分。至於爲什麼第二種方法總是返回#t的原因 - 這條線:

(else 'hit_the_bottom) 

...確實會得到執行,但因爲它是一個遞歸調用的一部分,它會被返回到該行:

((three (cdr L) target1 target2 target3 (+ sum (car L))) #t) 

而值'hit_the_bottom#t,所以整個程序最後會返回#t。請注意,在方案中,不是#f的所有都是#t,在這種情況下,特別是,'hit_the_bottom將被解釋爲#t。只是要清楚,真的是正在執行的else部分,運行這段代碼,你會看到印'hit_the_bottom在屏幕上只出現一次:

(define three 
    (lambda (L target1 target2 target3 sum) 
    (cond ((= target1 0) 
      (three L (car L) (cadr L) (caddr L) 0)) 
      ((null? L) 
      (= (- sum (+ target1 target2 target3)) 
       (+ target1 target2 target3))) 
      ((three (cdr L) target1 target2 target3 (+ sum (car L))) 
      #t) 
      (else (display 'hit_the_bottom) 'hit_the_bottom)))) 

(three '(1 2 3 6) 0 0 0 0) 
=> #t 
(three '(1 2 3 5) 0 0 0 0) 
=> hit_the_bottom #t 

最後,糾正第二種方法,用(else #f)替換最後一行它會按預期工作。

+1

你給了我一個更有效的選擇。然後,你非常好地解釋了我的問題,所以我現在完全明白了爲什麼發生了。另外,你給了一個修復程序,以便我的應用程序現在可以運行,並且我可以完成其他部分。你真了不起。謝謝! – Birdman 2013-04-22 03:43:49

+0

永遠是我的榮幸:) – 2013-04-22 04:03:13