2

Common Lisp とは異なり、Scheme には変数と関数に共通の名前空間が 1 つあります。しかし、マクロスもそこに落ちますか?

それは、それらが存在する時間によって分離できます。しかし、コンパイル時に、マクロがすべてエクスパンスである場合、リストやコンスなどの関数が確実に存在するため、実行時とコンパイル時の両方に存在します。

次に、たとえば次のように記述できますか。

(define (add a b) (+ a b))

(let-syntax ((add (lambda (x)
                    (syntax-case x ()
                      ((_ a ...) (syntax + a ...))))))
   (display (add 1 2 3))
   (display (reduce-left add 0 '(1 2 3))))

6 6 を取得しますか? または、逆に、マクロを定義してから関数を定義しますか? そして、そのような表現では: (add 1 2) どうなりますか? それは関数呼び出しですか、それともマクロ展開ですか?

4

1 に答える 1

2

はい、変数とマクロは同じ名前空間にあります。(プロシージャについては言及しませんでした。プロシージャは、数値や文字列など、変数に格納できる単なる値だからです。)

' 'の本体内ではlet-syntax、' add' は常にマクロを参照します。例の他の場所では、「追加」は手順を指します。

コードに 2 つのエラーがあることに注意してください。

  1. ' syntax' 式が正しくありません。である必要があります(syntax (+ a ...))
  2. 「reduce-left」の呼び出しで、マクロ「add」を引数としてプロシージャに渡すとエラーになります。

複雑なことを 1 つ挙げておきます: 最初に ' add' をトップレベル プロシージャとして定義し、次に 'add' に関して他のプロシージャを定義し、後で 'add' をトップレベル マクロとして再定義すると、結果は適切に定義されず、実装ごとに異なります。同様に、'add' がトップレベル マクロとして開始され、後でプロシージャとして再定義された場合。

于 2013-01-28T08:16:30.273 に答える