2011-01-31 36 views
2

我試圖完成這個練習;Lisp練習涉及列表操作

Write a Lisp function that takes as input a list of elements, such as (A B C) 

,並返回,其中每個元素的位置跟隨它的列表,如(A 1 B 2 -C 3)

我試圖與兩個函數來做到這一點,但它不能正常工作,我只是得到相同的列表。這裏是我的代碼:

(defun insert (index var userList) 
    (if (or (eql userList nil) (eql index 1)) 
      (cons var userList) 
      (cons (car userList) (insert (- index 1) var (cdr userList))))) 


(defun insertIndex (userList) 
    (setq len (length userList)) 
    (loop for x from 1 to len 
     do (insert x x userList))) 

插入函數似乎自行工作正常,但它似乎不會對循環做任何事情。我是新的lisp和任何幫助將不勝感激,在此先感謝。

回答

3

Lisp中的位置從0開始。在insertIndex中,未定義變量len。 LOOP不返回任何有用的值。

如果你想用遞歸求解它,解決方案要簡單得多。

您需要測試結束條件。如果列表爲空,則返回空列表。

否則用FIRST元素創建一個新列表,當前位置以及在列表的其餘部分調用該函數的結果,並且位置增加1。

(LIST* 1 2 '(3 4)) is shorter for (cons 1 (cons 2 '(3 4))). 

這裏是本地函數的例子。使用DEFUN創建頂級功能現在是您的任務。你只需要重寫代碼。 LABELS引入了一個潛在的遞歸本地函數。

(labels ((pos-list (list pos) 
      (if (null list) 
       '() 
       (list* (first list) 
         pos 
         (pos-list (rest list) (1+ pos)))))) 
    (pos-list '(a b c d e f) 0)) 
2

主要問題與您insertIndex功能是,loopdo條款是副作用而已,它不會改變loop的返回值。 (並且您的insert不存在副作用。)將元素添加到列表返回值的右邊loop子句是collect。 (也有appendnconc加入多個列表。)

這是一個工作功能:

(defun insert-index (list) 
    (loop for elt in list and i from 1 
    collect elt 
    collect i)) 

你約的insertinsertIndex功能的行爲整體預期似乎是有缺陷的。你需要得到一個更清晰的心理模型,即關於哪些功能是副作用的,哪些不是,以及是否需要副作用來解決某些特定問題。

此外,您不應該在Common Lisp中的未定義變量上調用setq。您需要首先使用let來引入一個新的局部變量。

小問題:CamelCase在Lisp中非常單一。在標識符中分離單詞的慣用方式是使用破折號,就像我在代碼示例中所做的那樣。你不需要做(eql something nil),有特殊的null函數來檢查是否有東西nil,例如, (null something)