Racket マクロを記述するコンテキストで、「3D 構文」とは何を意味しますか?
という言葉を何度か耳にしました。私が書いていたマクロを参照して一度含めます。しかし、それは少し前のことです。私はそれを修正しましたが、今では元々何が間違っていたのか正確に思い出せません。
また: 3D 構文は常に悪いですか? それともeval
(あなたがそれを使う必要があると思うなら、あなたはおそらく間違っていますが、専門家の手でいくつかの有効な使い方があります)のようなものですか?
構文オブジェクトは、通常、単なるシリアライズ可能なデータであると想定されています。3D 構文はこの条件を弱めます。単純なデータだけでなく、任意の値を忍び込ませることができます。それがそれらを「3d」にする理由です。それらは、構文オブジェクトから期待される通常のフラットなものを超える値です。
たとえば、lambda
値をこっそり入れることができます。
#lang racket
(define ns (make-base-namespace))
(define (set-next! n)
(parameterize ([current-namespace ns])
(eval #`(define next #,n)))) ;; <-- 3d-syntax here
(define (compute s)
(parameterize ([current-namespace ns])
(eval s)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define counter 0)
(set-next! (lambda ()
(set! counter (add1 counter))
counter))
(compute '(+ (next)
(next)
(next)
(next)))
このような値が存在するということは、おそらく、コンパイルのフェーズ全体で情報を漏らそうとする根拠のない試みを意味するためです。その結果、個別にコンパイルできない可能性があります。次のようなエラーが表示される場合:
write: cannot marshal value that is embedded in compiled code value
それは、マクロがバイトコードにシリアル化できない 3D 構文を生成したことが原因である可能性が最も高いです。
まれに、動的評価のコンテキストで 3D 構文が本当に必要になる場合があります。具体的な例として、DrRacket のデバッガーはプログラムの構文に注釈を付けて、関数アプリケーションがデバッガーの関数に直接コールバックするようにしたい場合があります。これにより、プログラム エディターでインタラクティブなコード カバレッジ カラーリングなどを行うことができます。その意味で、3d-syntax は、動的に評価されるコードとその周囲環境との間の通信チャネルとして機能できます。