2

私はこの演習を完了しようとしています。

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

、および(A 1 B 2 C 3)のように、各要素の位置がそれに続くリストを返します。

2つの関数でそれを実行しようとしていますが、正しく機能していません。同じリストを取得しているだけです。これが私のコードです:

(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です。よろしくお願いします。よろしくお願いします。

4

2 に答える 2

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))
于 2011-01-31T00:34:20.017 に答える
2

insertIndex関数の主な問題は、 のdo句がloop副作用のみを目的としており、 の戻り値を変更しないことloopです。(そして、あなたにinsertは副作用がありません。)loopリストの戻り値に要素を追加する正しい句はcollectです。(複数のリストに参加するともappendあります。)nconc

これは実用的な機能です:

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

insertおよび関数の動作に関するあなたの期待全体にはinsertIndex欠陥があるようです。副作用のある関数とそうでない関数、特定の問題を解決するために副作用が必要かどうかについて、より明確なメンタル モデルを取得する必要があります。

setqまた、 Common Lisp では未定義の変数を呼び出すべきではありません。let最初に使用して、新しいローカル変数を導入する必要があります。

マイナーポイント:キャメルケースは Lisp では非常に一義的です。識別子で単語を区切る慣用的な方法は、コード例で行ったように、ダッシュを使用することです。そして、あなたがする必要は(eql something nil)ありませnullん。nil(null something)

于 2011-02-03T02:43:14.653 に答える