2013-08-29 8 views
7

最近、私はLispの基礎についてたくさん考えてきました。私はP. GrahamのThe Roots of Lisp含むインターネット上のいくつかの説明書、および/または他の材料を読んだ:Lispの、quoteなぜ `unquote` Lispプリミティブがありませんか?

で根をデータにプリミティブその変更コードとして記述され、それによってを引用しますですが、同等の逆プリミティブ、つまりunquoteプリミティブがないようです。私はそれがevalのビジネスだと思ったが、evalは、データをコードに戻すことと同等ではない、字句のない環境でデータを実行することが多い。

Ergo、なぜ、unquote Lispプリミティブはありませんか?

+2

、私が何をしたいことは、 'unquote'自体(私は私の答えで述べたように、すでに提供されている)ではないという印象を受けるが、[の種類'local-eval'](http://www.gnu.org/software/guile/manual/html_node/Local-Evaluation.html)で、JavaScriptの' eval'(語彙変数が利用可能)と同じように動作します。 –

+1

@ ChrisJester-Youngはい、そうです。 – SaltyEgg

+0

@ ChrisJester-Youngそして私が知りたいのは、なぜこの種の 'quote 'がプリミティブでないかです。なぜ、引用符があったのですか?作者がその逆関数を含まないのはなぜですか? – SaltyEgg

答えて

8

unquotequasiquoteの文脈においてのみ有用であり、そしてquasiquote(すなわち背後quoteを使用)マクロとして実装することができます。したがって、unquoteプリミティブを持つ必要はありません。 quasiquoteマクロは単に見つかったとしてunquoteシンボルを扱います。

quasiquoteはバッククォートの引用のためのスキーム名でこのように:。。

`(foo bar ,baz) 

スキームで
(quasiquote (foo bar (unquote baz))) 

として読み込まれる)


はここで非常に簡単ですScheme quasiquoteマクロ(リストを扱うのは標準の私もLispのでは比較的新しいですが、私は何を考えていたのだと思います

(define-syntax quasiquote 
    (syntax-rules (unquote unquote-splicing) 
    (`,datum 
    datum) 
    (`(,@datum . next) 
    (append datum `next)) 
    (`(datum . next) 
    (cons `datum `next)) 
    (`datum 
    'datum))) 
+0

マクロはランタイム実行前​​に展開されています。この種のunquoteは実行時環境のシンボルには影響しません。 – SaltyEgg

+0

Schemeでは、マクロはシンボルだけでなく、字句情報でタグ付けされた識別子で動作します。 (Yay hygienic macros!)私の例が適切に対処していないと考える特定の例がない限り。 –

+0

私はSchemeに慣れていません。私はCommon Lispのケースをテストしましたが、それはうまくいきません。 – SaltyEgg

0

:すべての標準的な読者の略語を使用して

(define-syntax quasiquote 
    (syntax-rules (unquote unquote-splicing) 
    ((quasiquote (unquote datum)) 
    datum) 
    ((quasiquote ((unquote-splicing datum) . next)) 
    (append datum (quasiquote next))) 
    ((quasiquote (datum . next)) 
    (cons (quasiquote datum) (quasiquote next))) 
    ((quasiquote datum) 
    (quote datum)))) 

同等のバージョン:ベクトルや他のデータ型を扱う)約evalです。 evalはデータをコードに戻す方法です。

つまり、単純な機能を考えてみましょう。

(defun foo (a b c) (list a b c)) 

あなたはこのような何かを行う場合次に、あなたはシンボルのリストを取得:

CL-USER> (foo 'a 'b 'c) 
(A B C) 

あなたが前に引用符を追加する場合は、関数の呼び出し自体がデータの一部として扱われます(リスト):

CL-USER> ''(foo 'a 'b 'c) 
'(FOO 'A 'B 'C) 

CL-USER> '(foo 'a 'b 'c) 
(FOO 'A 'B 'C) 

一つ以上の引用を追加するには、期待される効果を有しています

evalで元に戻してください。本質的にはquoteの逆演算と考えることができます。これは逆です。 x軸はデータ形式です。 y軸はコード形式です。うまくいけば、この(幾分伸ばした)類推は意味をなさないでしょう。

CL-USER> (eval ''(foo 'a 'b 'c)) 
(FOO 'A 'B 'C) 

あなたは、私が行に2つのeval Sを連鎖さ何が起こるかを推測することはできますか? ここでは、次のとおりです。

あなたの質問を読み直す
CL-USER> (eval (eval ''(foo 'a 'b 'c))) 
(A B C) 
関連する問題