違いは何ですか
(cons 2 3)
と
'(2 . 3)
Lispで?
REPL では同じ値に評価されますが、まったく同じではありません。コンスセルが破壊的に変更されるこれらの例を考えてみましょう:
TEST> (defun literal-cons ()
(let ((cons '(1 . 2)))
(incf (cdr cons))
cons))
LITERAL-CONS
TEST> (literal-cons)
(1 . 3)
TEST> (literal-cons)
(1 . 4)
TEST> (literal-cons)
(1 . 5)
これと比較して:
TEST> (defun non-literal-cons ()
(let ((cons (cons 1 2)))
(incf (cdr cons))
cons))
NON-LITERAL-CONS
TEST> (non-literal-cons)
(1 . 3)
TEST> (non-literal-cons)
(1 . 3)
最初のバージョンでは、コード自体のリテラルコンス セルを変更しています (したがって、これは自己変更コードです)。2 番目のバージョンでは、コンス セルはリテラルではありません。コードが呼び出されるたびに生成され、この新しいコンス セルのみが変更されます。
TEST> (function-lambda-expression #'literal-cons)
(LAMBDA NIL
(DECLARE (CCL::GLOBAL-FUNCTION-NAME LITERAL-CONS))
(BLOCK LITERAL-CONS (LET ((CONS '(1 . 5))) (INCF (CDR CONS)) CONS))) ;; notice the '(1 . 5)
NIL
LITERAL-CONS
これは、破壊的な操作を使用するときに微妙なバグにつながる可能性があるため、コード内のそのようなリテラル オブジェクトには注意する必要があります。これは、コンス セルから構築されたリスト リテラル ( '(1 2 3)vs. ) にも影響します。(list 1 2 3)
HyperSpecから:
文字通りの形容詞。(オブジェクトの) プログラムによって計算されるのではなく、プログラム内で直接参照される。つまり、引用形式のデータとして表示されるか、オブジェクトが自己評価オブジェクトの場合は、引用されていないデータとして表示されます。「(cons "one" '("two")) の形式では、式 "one"、("two")、および "two" はリテラル オブジェクトです。」
どちらも類似した構造を持つオブジェクトです。つまり、どちらもコンス セルであり、CAR の位置に 2 つ、CDR の位置に 3 つです。
それらの主な違いは、'(2 . 3) は定数であり、(cons 2 3) は新しいコンス セルを生成することです。以下のように 2 つの (似たような) 関数を使用すると、これらの違いが明らかになります。
(defun a ()
(let ((v (cons 2 3)))
(incf (car v))
v)
(defun b ()
(let ((v '(2 . 3)))
(incf (car v))
v)
b を呼び出し続けると、かなりの数の実装が '(3 . 3) '(4 . 3) などを返します。
'(2 . 3)はドット ペアです。
(cons 2 3)ドット ペアも作成します。したがって、これらは同じものに評価されるはずです。
したがって、1 つはドット ペアのリテラルであり、もう 1 つはドット ペアを作成します。
(1 . 2)consセルの s 式構文です。コンスセルには、 として 1 と としてcar2 がありcdrます。
'(1 . 2)の前に引用文字が付いているのは、 の短い表記です(quote (1 . 2))。はquote、エバリュエータに、囲まれているフォームを評価せず (!)、そのまま返すように指示します。この引用されたフォームの値は、フォームそのものです。quote言う:評価しないでください。Common Lisp では、これは定数リテラル データと見なすことができます。
(cons 1 2)は、前に関数があり、1 と 2 の 2 つの引数を持つ Lisp フォームですcons。このフォームを評価すると、関数consは引数 1 と 2 で呼び出されます。定義により、その引数がandconsである新しいコンス セルを返します。したがって、評価するたびに新しいコンスセルを返します。carcdr(cons 1 2)
それらは同じではなく、同じです。
記号引用符 (') は、「これを評価せずにこのリストを作成する」という関数です。例: '(* 2 2 ) ; リストを作成します ( * 2 2 ) (list (* 2 2) ; リストが評価されるので (4) を作成します。
関数 cons は関連するペアを作成し、これだけです。例: (cons (abc) (1 2 3) ) ;create (abc . 1 2 3) (cons a (1 2 3 4) ) ;create (a. 1 2 3 4)
この場合、使用した 2 つの関数は同じことを行いますが、異なる方法を使用します。引用符 (') は記号引用符 (') の前にリストを作成するだけであり、cons 関数は、関数に指定した "itens" thar と関連付けられたペアを作成するだけだからです。