2014-10-26 60 views
0

我在Scheme中編寫了一個程序,該程序接收一個包含數字和兩個空列表的列表。我希望將正數加入到一個列表中,而將負數放在另一個列表中。最後,我想返回兩個列表的連接。我爲此目的使用附加這樣的:在列表上遞歸時返回空列表

(define (joinLists listInic list1 list2) 
    (if (empty? listInic) 
     (append list1 list2) 
     (begin 
     (if (> (car listInic) 0) 
      (append list1 (car listInic)) 
      (append list2 (car listInic)) 
      ) 
     (joinLists (cdr listInic) list1 list2)))) 

但是當我喜歡的一些數據運行:

(joinLists '(4 5 -5 -4)'()「())

它總是返回空列表()

我做錯了什麼?

回答

2

您使用的方式append是錯誤的。當然,我們可以這樣寫:

(append list1 (list (car listInic))) ; second argument should be a list 

...但list1參數被修改原地的,而不是創建一個新的名單 - 而且考慮到你沒有給它分配或圍繞把它作爲aa參數,那麼新的列表將會丟失 - 這就是爲什麼總是得到一個空列表的原因,列表參數從未被修改過。我們必須做這樣的事情:

(define (joinLists listInic list1 list2) 
    (cond ((empty? listInic) 
     (list list1 list2)) 
     ((positive? (car listInic)) 
     (joinLists (cdr listInic) (cons (car listInic) list1) list2)) 
     (else 
     (joinLists (cdr listInic) list1 (cons (car listInic) list2))))) 

幾點考慮:

  • 這是更好地使用cond當我們有多個條件,而不是嵌套if S和begin小號
  • 使用positive?測試一個數是否大於零
  • 將結果作爲參數傳遞,如上所述,只需附加它們(或委託它們,或其他),不會修改l派就地
  • 使用cons只要有可能,而不是append - 這是便宜得多,因爲它在列表的頭部添加元素,而append遍歷整個列表,並創建一個新的列表,除了它的最後一個參數也應是一個列表,用於建立一個適當的列表

關於最後一點,如果你絕對必須從輸入列表保持原來的順序,即便如此,它會更好地使用cons然後reverse輸出在最後列出 - 再次,避免append。例如,以下是樣本輸入的輸出:

(joinLists '(4 5 -5 -4) '() '()) 
=> '((5 4) (-4 -5)) 
2

append不會更改列表的值,它會生成一個新列表,並附加給定的項目。由於您實際上沒有使用append生成的值,因此您對append的使用完全沒有影響。作爲一般的經驗法則,使用begin只有在您調用的函數具有副作用時纔有意義,而append則不具有副作用。

您應該做的是將append的結果作爲參數傳遞給joinLists的遞歸調用。