11

コンピュータプログラムの構造と解釈の演習を通して、私はゆっくりと自分の道を進んできました。セクション1.1.5では、適用評価と通常順序評価について説明し、その後、このトピックがテキストで何度か取り上げられています。インタープリターは適用順序評価を使用するためdisplay、コードにデバッグステートメントを挿入するだけで、それがどのように機能するかを正確に確認できます。通常の順序の評価でも同じことができると理解するのに役立ちます。

適用順序ではなく通常順序評価を使用して実装されたScheme(またはLisp)インタープリターを知っている人はいますか?

アップデート:

これは、SICPで提供されているものから変更された短い例です。add引数を出力するための独自のプロシージャを定義squareし、本のプロシージャを使用します。

(define (add x y)
  (display x)
  (display y)
  (newline)
  (+ x y))

(define (square x) (* x x))

(square (add 1 2))ここで、適用順序評価を使用して短いプログラムを実行すると、の結果は1回だけ計算され、その後プロシージャ(add 1 2)に渡されます。squareオペランド12は、最終結果の前に1回出力する必要があります。これをインタプリタで実行して、これが発生することを確認できます。

> (square (add 1 2))
12
9

ただし、通常の順序の評価を使用すると、単一のオペランドをプロシージャに(add 1 2)コピーする必要があります。これは、として評価されます。オペランドは、最終結果の前に2回出力する必要があります。square(* (add 1 2) (add 1 2))12

これを通常の順序の評価を行うインタープリターで実行して、これが実際にどのように機能するかを確認できるようにしたいと思います。

4

2 に答える 2

7

結局のところ、Schemeには、本質的に通常の順序の評価者がすでに付属しています。これらはおそらくよく耳にする伝説のマクロであり、セクション1.1.4〜1.1.5の例を書き直して、プロシージャアプリケーションの代わりにマクロ展開を簡単に使用できるようにします。

(定義(印刷。アイテム)
  (各表示項目))

(define-macro(add xy)
  `(begin(print" [ADD "'、x" "'、y"] ")
          (+、x、y)))

(define-macro(mul xy)
  `(begin(print" [MUL "'、x" "'、y"] ")
          (*、x、y)))

(define-macro(square x)
  `(begin(print" [SQUARE "'、x"] ")
          (mul、x、x)))

(define-macro(sum-of-squares xy)
  `(begin(print" [SUM-OF-SQUARES "'、x" "'、y"] ")
          (add(square、x)(square、y))))

(define-macro(fa)
  `(begin(print" [F "'、a"] ")
          (二乗和(add、a 1)(mul、a 2))))

PRINTを無視してください。それらのロジックは、テキストの現在の場所を少し超えていますが、多くのDISPLAYの省略形にすぎません。実際には、システムのマクロ拡張機能を使用するために、印刷によるトレースを完全にやめたいと思うでしょう。ただし、これは実装によって異なります(たとえば、Ypsilonでは使用します(macro-expand '(f 5)))。

これらの定義をロードすると(DEFINE-MACROは非標準ですが、ほとんどのスキームで提供されているため、実際には問題にはなりません)、(f 5)本のように評価すると印刷されます(もちろん私はそれをきれいにしました)少し上):

[F 5]
[SUM-OF-SQUARES(add 5 1)(mul 5 2)]
[ADD(square(add 5 1))(square(mul 5 2))]
     [SQUARE(5 1を追加)]
     [MUL(5 1を追加)(5 1を追加)]
          [51を追加]
                    [51を追加]
                                [SQUARE(mul 5 2)]
                                [MUL(mul 5 2)(mul 5 2)]
                                     [MUL 5 2]
                                               [MUL 5 2]
136

それは多かれ少なかれ本がプロセスがどうあるべきかを説明しているものです。


これらの種類のマクロを作成することは、基本的に通常のプロシージャを作成することと似ていますが、

  • DEFINEの代わりに、DEFINE-MACROを使用します。
  • 本体には暗黙のBEGINがないため、複数の式がある場合は独自のBEGINを指定する必要があります。
  • 全身表現の前にアクサングラーブが付いています。
  • パラメータのすべてのインスタンスには、接頭辞としてコンマが付いています。

それがSchemeマクロ101の作成です。

全体として、これはSICPの最初の章だけで誰かにマクロを表示するのは少しばかげています。しかし、あなたが望むことをするためにラケットを変更するのが非常に難しいと言うなら(そしてラケットをまったく使用していない人もいます)、ここに別の方法があります。

于 2010-07-10T04:59:45.623 に答える
6

ラケットには怠惰な言葉があります。単純なラケット モジュールと遅延モジュールで構成されたプログラムを作成できるため、単なるインタープリターよりも優れています。

プリントアウトを使用したデバッグについては、この怠惰な言語で行うことができ、Haskell の unsafe IO に似たものを取得します。ただし、これはまだ時々混乱する可能性があります。(そして、インタープリターにプリントアウトをプラグインさせたい場合は、遅延評価に従うため、混乱することもあります...)

于 2010-07-08T16:49:58.303 に答える