2017-04-30 47 views
1

對於Scheme編程語言來說,我是一個相當新的東西,我只是無法弄清楚這兩段代碼之間的區別,特別是我指出的那些代碼段。Scheme null?聲明

;program that returns the Nth element in a list where N is an integer argument 

(define getElement 
(lambda (N L) 
(cond 
    ((null? L) '()) 
    ((= N 1) (car L)) 
    (#t(getElement (- N 1) (cdr L)));this line 
) 
) 
) 

;takes a list L and a number N and returns the list L but with the first N elements removed 
(define remove 
(lambda (N L) 
(cond 
    ((null? L) '()) 
    ((= N 0) L) 
    (#t(remove (- N 1) (cdr L)));and this line 
) 
) 
) 

爲什麼這些程序的輸出如此不同?除了檢查列表是否爲空以及整數N是否爲特定值之外,我無法看到條件語句對程序輸出後2行有什麼影響,請執行此操作。

這是我的第一篇文章,所以任何的建議是值得歡迎的

回答

2

兩個功能是遞歸的並使用相同的遞歸策略。但是,當你到達遞歸的底部時,他們會做出非常不同的事情。

每個函數都將n減1,並將列表減少一個元素,並在新的上下文中調用它自己。 所以,在這兩種情況下,列表(至少在函數的參數中表示的)不斷縮短。 remove函數返回整個剩餘列表。由於在remove函數的參數中已經從列表的副本中刪除了一些元素,因此這會返回一個縮短的列表。 但是,第n個元素函數不返回列表;它返回(car l),或返回l中包含的cons單元中的元素。也就是說,它只返回列表的當前元素。 這就是他們產生不同結果的原因。

0

您表示的行也是一樣的。 絕對沒有區別!它遞歸到自身,索引減少,列表更改爲cdr

當基本情況命中第一個返回第一個元素,第二個返回列表。

(getElement 1 '(1 2 3)) ; ==> 1, Since it does (car L) 
(remove 0 '(1 2 3))  ; ==> (1 2 3), since it does L 

現在,如果你getElement工作就像list-ref0應該已經基本情況,同爲remove。當索引爲零之前列表爲空時,它也應該發出一個錯誤信號。這是更喜歡它:

#!r6rs 
(import (rnrs)) 
(define (my-list-ref lst pos) 
    (cond ((null? lst) (raise 'list-too-short)) 
     ((zero? pos) (car lst)) 
     (else (my-list-ref (cdr lst) (- pos 1))))) 

(my-list-ref '() 1) 
; ==> uncaught exception: list-too-short 
1

正如你所說,

如果整數N有一定的價值,這樣做

不同的是,在「做」 。

第一個,

((= N 1) (car L)) 

說:「得到一個列表的第一個元素,以列表的car」。

第二個,

((= N 0) L) 

說:「用來刪除列表中沒有的元素,返回整個列表」。

的遞歸完全一樣,但第一個寫着「從列表中的cdr獲得元素N - 1」,而第二個寫着「從列表中刪除的cdrN - 1元素」。

(它看起來像第一功能已經從Lisp語言,其中nil是「假y」的翻譯。更計劃-Y函數將返回#f。)