2

ループ内で使用されるリストがあり、各反復で、リストを永続的に変更する関数を適用します(要素のポップと追加)。問題は、元のリストがゼロの場合は常に変更されないことです。どうすればこの問題を解決できますか?私のコードを以下に示します

(defun looping-func ()
    (let ((queue '(2)))
          (loop while (not (null queue)) do
            (let (  (num (pop queue)))
                (if (oddp num)
                    (format t "~%~A success" num)
                    (progn (format t "~%fail")
                           (add-to-list (1+ num) queue)))))))

(defun add-to-list (elem l)
    (nconc l (list elem)))

リストに複数の要素が含まれている場合、コードは意図したとおりに機能します。正確に1つの要素が含まれている場合、その要素がポップされてリストがnilになると、適用された変更はリストに永続的ではなくなります。これは、nconcがどのように定義されているかによるものだと思います。最初の引数がnilの場合、変更せずに2番目の引数を返すだけです。これについてどうやって行くかについてのアイデアはありますか?

PS:上記のコードは役に立たないことは知っていますが、残念ながらコードを投稿できない学校のプロジェクトに同じコンセプトを使用しています。

4

3 に答える 3

3

変化する

(add-to-list (1+ num) queue)

(setq queue (add-to-list (1+ num) queue))

で「拡張」することはできませnilnconc

(nconc nil . lists)

と同等です

(nconc . lists)

add-to-listそのため、の結果を入れる必要がありますqueue

于 2012-10-19T03:02:48.867 に答える
3

リストの最後に要素を追加しないでください。

一度もない。

Lisp のリストは、head への要素の追加が安価になるように設計されています。最後に追加すると、コストがかかる可能性があります。

LIFO キューを実装するには、別の実装が必要です。

実行時にソース コード内の定数リテラル データを変更しないでください。

コードを適切にインデントします。

于 2012-10-20T08:53:05.957 に答える
1

これは演習であると想定したため、これは日常の練習では使用しない例です。マクロを使用する必要がありますpush。これはおそらくそれに似た動作をします。

(defmacro push-example (item list)
  (let ((the-list list))                ; we do this to prevent
                                        ; multiple evaluations
                                        ; of the `list' argument
  `(setq ,the-list (cons ,item ,the-list))))

(defparameter *test* nil)

(push-example 'foo *test*) ;; (foo)
*test* ;; (foo)

マクロを要求しなかった(関数を要求した)一方で、ダグの答えは技術的にはより正確です。これは、マクロを介したコード生成を使用してそれを実行できた方法を示しています。これが基本的に関数と同じことをしていることに注意してください。ただし、setqそうでない場合は、呼び出しをカプセル化できる点が異なります。

于 2012-10-19T10:13:36.357 に答える