2015-04-01 70 views
1
(define mystery2 
    (lambda (L) 
    (if (null? L) 
     L 
     (begin 
      (displayln L) 
      (append (mystery2 (cdr L)) 
        (list (car L))))))) 

,我通過(mystery2 '((1 2) (3 4) 5 6))球拍開始形式

運行它在這裏,我不知道什麼是「開始」功能一樣。

此外,當我寫「displayln L」它只給我們((1 2) (3 4) 5 6))它不應該打印出遞減值,因爲它是遞歸?

請幫助我理解爲什麼在這裏使用「開始」,而displayln是這樣工作的。

代碼本身沒有問題。

+0

注意它叫「神祕」而不是它本身,所以我們不能說它是遞歸的。它可能是相互遞歸的,但「神祕」需要調用「mystery2」。 – Sylwester 2015-04-01 06:35:36

回答

2

使用begin表單,因爲if只允許在每個分支中有1個表達式。

更直觀的例子可能是調試。假設你正在編寫困難的代碼,你想看看哪個分支被執行。

原始代碼:

(if (true? some-value) 
    (dostuff) 
    (dostuff2)) 

但你不知道哪個分支得到執行,所以你可能想打印每當執行任一分支的消息。但是因爲Scheme只允許在每個分支中使用單個表達式,所以不能將它們放在那裏。你必須用一個表達式將它們粘在一起,用begin

(if (true? some-value) 
    (begin 
     (display "some-value was true") 
     (dostuff)) 
    (begin 
     (display "some-value was false") 
     (dostuff2))) 

Begin需要任意數量的表達式並執行它們中的每一個,但只返回正文中最後一個表達式的結果。

+0

感謝您的回覆!然後我想知道在「displayln」中,它只打印出一個列表。它不應該打印出更多?既然是遞歸,我認爲它應該多次調用「displayln」,這意味着多個顯示? – harumomo503 2015-04-01 16:34:40

+0

如果'神祕'呼叫'神祕',當然。但是我們看不到「神祕」功能的代碼。 – 2015-04-01 17:07:05

+0

對......!謝謝! – harumomo503 2015-04-01 21:50:13

2

首先,我回答你的問題:

begin形式(它不是一個函數)只評估其子表達式,並返回最後一個的值。

因此,如果您評估(begin 3 4 5),它將僅返回5。如果你評估(begin (+ 3 4) (+ 9 1)),你會得到10

所以......你可能會問,爲什麼這會有用。答案是有些表達式會導致所謂的「副作用」。 displayln就是其中之一;它會導致顯示一個值。

不過,讓我們退後一步。這裏的祕訣就是:嘗試一下!球拍是一種對實驗非常友好的語言;幾乎所有的價值觀都是直接「可寫」的形式,你可以把小表達出來並評估它們看看它們產生了什麼。

隨意問後續問題!

+0

哦。那麼'開始'形式用於評估子表達式,但也有助於避免副作用,如'displayln'?球拍中的「副作用」意味着什麼? – harumomo503 2015-04-01 04:44:41

+0

@HAruMOmo沒有副作用,唯一的結果是返回的值,它只是基於參數。例如。如果你讀,寫,存儲或檢索的東西是副作用。在你的例子'displayln'中可能有打印某物到終端的副作用。 – Sylwester 2015-04-01 09:11:50

+0

謝謝你的迴應! – harumomo503 2015-04-01 21:50:35

0

begin將幾個表達式換成block。使用cond而不是if的原因之一是,結果會自動包裝在一個塊中。

(define mystery2 
    (lambda (L) 
    (cond [(null? L) 
      L] 
      [else 
      (displayln L) 
      (append (mystery2 (cdr L)) 
        (list (car L)))])))