お酒好きのおしりトラブル対策とは

お世話になります。
Emacs Lispについて勉強しています
今は、リスト、consセルについて勉強しています。
以下、拙い質問になるかと思いますが、よろしくお願いします。

Lisp Interactionモードのバッファに、

'(1 2 3)

というリストを書いて行末でC-jを押下すると

(1 2 3)

という式を返します。

しかし、

(1 2 3)

という式を書いて行末でC-jを押下すると

Debugger entered--Lisp error: (invalid-function 1)

というエラーになります。

これは、1が関数、2と3が引数として評価されるからですね。

さて、リストではなく「consセル」を作るとします。

(1 . 2)

と書いてC-jを押下すると、やはり

Debugger entered--Lisp error: (invalid-function 1)

というエラーになります。

'(1 . 2)

であれば

(1 . 2)

と、正しくconsセルが出来ます。

'(1 . nil)

であれば

(1)

というリストを返します。
これは、cdr部がnilであるconsセルはリストになるからですね。

では、3と、「1とnilからなるリスト」のconsセルを作って、結果的に(3 1)というリストにしようとします。

'(3 . '(1 . nil))

この場合は、予想に反して

(3 quote (1))

となります。

'(3 . (1 . nil))

であれば、

(3 1)

となります。一方、

(3 . (1 . nil))


とすると、

Debugger entered--Lisp error: (invalid-function 3)

となります。


まとめると、
3と、「1とnilからなるリスト」のconsセルを作って、結果的に(3 1)というリストにしようとした場合は、
'(3 . (1 . nil))
のように外側のconsセルはクォートし、内側のconsセルはクォートしない、ということになりますね。
このクォートの振る舞いの違いはなぜでしょうか。
よろしくお願いします。

このQ&Aに関連する最新のQ&A

リスト C++」に関するQ&A: C# リストの検索

A 回答 (3件)

ん~, どこに着目しているのかがよくわからない....



まず Lisp インタプリタの動作としては「S式を全部読み込んでから評価」です. で #1 にも書いたように 'x は読み込んだ直後, 評価よりも前に (quote x) に変換されます. これはもちろん
(* 3 (+ 2 1))
でも同じで, 「(* 3 (+ 2 1)」まで読み込んだ時点 (まだ最後のかっこは読み込んでいません) で「(+ 2 1)」というリストは完成してるけど, この時点で評価しているわけではありません. S式全体を読み込んでからおもむろに評価を始めます.

でスペシャルフォーム quote 自体は「引数 (1個) を評価せずそのまま返す」から,
(quote (* 3 (+ 2 1)))
を評価した結果は引数である (* 3 (+ 2 1)) そのものです. これに対し「*」のような普通の関数は「全ての引数を評価し, 得られた値に対して当該関数 (今の場合は『*』) を適用する」という動作をします. つまり
(* 3 (+ 2 1))
に対しては
1. S式全体はリストで, その先頭要素「*」は「普通の関数」である
2. だからすべての引数 (今の場合は「3」と「(+ 2 1)」) を評価する
3. 最後に得られた値に対して関数「*」を適用する
結果 (6 ではなく) 9 という値が得られます.
    • good
    • 0
この回答へのお礼

ありがとうございます!
たしかに関数とスペシャルフォームというものの差が分かっていませんでした。
事情を説明すると、自分的にはEmacsのカスタマイズをちょこちょこっとやるつもりで、薄い本に取り組んでいたのですが、Lispそのものの説明は割愛されているので、疑問が湧いてしまいました。
やはりLispそのものの定義を明らかにしないと無理筋だと思いますので、そういう本を勉強しようと思います。
(追加質問で申し訳ありませんが、そういう勉強に適したLispの本のおすすめがあれば教えてください。)

重ね重ねありがとうございます。

お礼日時:2013/11/14 09:33

単純に言えば、quote は渡された引数をすべて(あなたの言葉を使えば)「関数扱い」しないからです。


すなわち、
'('x) = (quote (quote x))
を評価すると単に
(quote x)
になります。
おそらくあなたは、普通の関数から類推して(例えば (+ (* 2 3) 1) = (+ 6 1) = 7 のように) quote の引数も評価されると思われたのでしょうが、
quote は関数ではなく特殊形式と呼ばれるもので、内側の関数を(当然、特殊形式も)評価しません。
    • good
    • 0
この回答へのお礼

こちらもありがとうございます。
関数と特殊形式ですね。理解しました。

お礼日時:2013/11/14 09:34

Emacs Lisp だとどう説明するんだったっけ.... 以下「普通の Lisp」の場合 (内容自体は Emacs Lisp でも同じですが, 表現は違うかもしれません):



シングルクォートは「スペシャルフォーム quote の省略形」として読み込まれます. つまり
'x
と入力するとあたかも
(quote x)
と入力したかのように読み込まれ, これが評価されることで
x
が得られます.


'(3 . '(1 . nil))

(quote (3 . (quote (1 . nil))))
と書いたものとみなされますから, 評価すれば
(3 . (quote (1 . nil)))
すなわち
(3 quote (1))
となります.

この回答への補足

お礼ありがとうございます。
私が知りたいのは、

(1 . nil) ;;; Debugger entered--Lisp error: (invalid-function 1)
;;; carが関数扱いされてエラー

'(1 . nil)
(1)
;;; carが関数扱いされない<=当然

'(3 . (1 . nil))
(3 1)
;;; 内側のconsセルのcar(1)が関数扱いされない<=なぜ?

のように、consセルのcdr側になるときはquoteしなくても、(の直後の要素が関数扱いされない理由です。

リストの場合も、

'(* 3 (+ 2 1))
(* 3 (+ 2 1))

(* 3 (+ 2 1))
6

のように、先頭で一度クォートすれば、要素の中にリストがあっても第一要素を関数扱いしませんね。
この理由です。。

補足日時:2013/11/13 09:17
    • good
    • 0
この回答へのお礼

お礼ありがとうございますではなくて、回答ありがとうございますです。失礼しました!!!
本当にありがとうございます!!!!

お礼日時:2013/11/13 09:18

このQ&Aに関連する人気のQ&A

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


人気Q&Aランキング