2011-01-31 5 views
2

私はこの練習を完了しようとしています。リストの操作を伴うLispの練習

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

、私は2つの機能とそれをしようとしている

そのような(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機能の主な問題は、副作用が唯一、それがloopの戻り値を変更しないためloopdo句があるということです。 (そして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)