プロが教える店舗&オフィスのセキュリティ対策術

「初めての人のためのLISP[増補改訂版]」のP150のリストを逆順に関数がよくわかりません。
以下がその関数です。

(defun nreverse (x) (nrev2 x nil))

(defun nrev2 (x r)
(cond ((null x) r)
(t (nrev2 (cdr x) x)
(rplacd x r) )))

xがnilになるまで再帰を繰り返し、((null x) r) で再帰を戻りますがなぜs (rplacd x r)でリストが逆順になるんでしょうか。例えばxを(a b c)とすると

x:(a b c) r:nil

x:(b c) r:(a b c)

x:(c) r:(b c)

x:nil r:(c)

rplacd (c) (b c)

rplacd (b c) (a b c)

rplacd (a b c) nil

となるのですが、これじゃあ全然リストは逆順になりませんよね。

誰が教えてください、お願いします。

ちなみにrplacd は第一引数のcdrを第二引数に変換する関数です。

A 回答 (4件)

「'(c)と'(b c)のcdrのcは実体は同じということでしょうか?」


という聞き方だと
(eq (car '(c)) (cadr '(b c))) は常に t を返すか?
と解釈したくなる (これは正しい) んだけど, それはおそらく「本来聞きたいこと」じゃないよね?

「'(c) で表される consセルと '(b c) の cdr である consセルの実体が同じかどうか」ということであればは一般には不定 (等しいこともあれば等しくないこともある). つまり
(equal '(c) (cdr '(b c))) => t
(eql '(c) (cdr '(b c))) => t または nil
(eq '(c) (cdr '(b c))) => t または nil
ということになる.

もっとも, 今の場合には eq の意味でも同じであることが (プログラムの作り方から) 保証される.
    • good
    • 0
この回答へのお礼

なんとなくわかりました。
ありがとうございます。

お礼日時:2011/12/15 00:49

質問文にある関数はB子さんが解答したもので、正しく動かないとK先生に指摘されたものではないですか?



それをおいてもこの関数は一つのリストを共有して直接書きかえているので、質問文の後半にあるめも書きのように
考えてしまうと混乱してしまうと思います。
#2の方の回答で示されているリンク先にある図をよく見て追いかけてみてください。

つか前の質問どうしたの?

この回答への補足

正しく動かないけどリストの逆順は行われている
という説明だったので本質的には変わらないと思います

補足日時:2011/12/11 22:56
    • good
    • 0

この人のとか。


http://webcache.googleusercontent.com/search?q=c …

質問文のコードと違っているのは、増補改訂版だから?

この回答への補足

おお!まさに聞きたい説明です!
ありがとうございます。

このページの 3.返り値 で (rplacd '(c) '(b c)) のところで carがcのセルのcdrからcarがbのセルに繋がり、そのセルのcdrはまた同じcarがcのセルに繋がっていますよね。これってつまり '(c)と'(b c)のcdrのcは実体は同じということでしょうか?

補足日時:2011/12/11 23:55
    • good
    • 0

rplacdの第二引数からcarで取り出す処理を忘れてる(誤植?)のではないでしょうか。



rplacd(x car(r))

ならうまく動きそう。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!