13

このレッスンのコードをオンラインで見つけました (http://groups.csail.mit.edu/mac/ftpdir/6.001-fall91/ps4/matcher-from-lecture.scm)。それをデバッグしようとしています。このコードは、Sussman が書いたものとかなり似ています。

;;; Scheme code from the Pattern Matcher lecture

;; Pattern Matching and Simplification

(define (match pattern expression dictionary)
  (cond ((eq? dictionary 'failed) 'failed)
        ((atom? pattern)
         (if (atom? expression)
             (if (eq? pattern expression)
                 dictionary
                 'failed)
             'failed))
        ((arbitrary-constant? pattern)
         (if (constant? expression)
             (extend-dictionary pattern expression dictionary)
             'failed))
        ((arbitrary-variable? pattern)
         (if (variable? expression)
             (extend-dictionary pattern expression dictionary)
             'failed))
        ((arbitrary-expression? pattern)
         (extend-dictionary pattern expression dictionary))
        ((atom? expression) 'failed)
        (else
         (match (cdr pattern)
                (cdr expression)
                (match (car pattern)
                       (car expression)
                       dictionary)))))

(define (instantiate skeleton dictionary)
  (cond ((atom? skeleton) skeleton)
        ((skeleton-evaluation? skeleton)
         (evaluate (evaluation-expression skeleton)
                   dictionary))
        (else (cons (instantiate (car skeleton) dictionary)
                    (instantiate (cdr skeleton) dictionary)))))

(define (simplifier the-rules)
  (define (simplify-exp exp)
    (try-rules (if (compound? exp)
                   (simplify-parts exp)
                   exp)))
  (define (simplify-parts exp)
    (if (null? exp)
        '()
        (cons (simplify-exp   (car exp))
              (simplify-parts (cdr exp)))))
  (define (try-rules exp)
    (define (scan rules)
      (if (null? rules)
          exp
          (let ((dictionary (match (pattern (car rules))
                                   exp
                                   (make-empty-dictionary))))
            (if (eq? dictionary 'failed)
                (scan (cdr rules))
                (simplify-exp (instantiate (skeleton (car rules))
                                           dictionary))))))
    (scan the-rules))
  simplify-exp)

;; Dictionaries 

(define (make-empty-dictionary) '())

(define (extend-dictionary pat dat dictionary)
  (let ((vname (variable-name pat)))
    (let ((v (assq vname dictionary)))
      (cond ((null? v)
             (cons (list vname dat) dictionary))
            ((eq? (cadr v) dat) dictionary)
            (else 'failed)))))

(define (lookup var dictionary)
  (let ((v (assq var dictionary)))
    (if (null? v)
        var
        (cadr v))))

;; Expressions

(define (compound? exp) (pair?   exp))
(define (constant? exp) (number? exp))
(define (variable? exp) (atom?   exp))

;; Rules

(define (pattern  rule) (car  rule))
(define (skeleton rule) (cadr rule))

;; Patterns

(define (arbitrary-constant?    pattern)
  (if (pair? pattern) (eq? (car pattern) '?c) false))

(define (arbitrary-expression?  pattern)
  (if (pair? pattern) (eq? (car pattern) '? ) false))

(define (arbitrary-variable?    pattern)
  (if (pair? pattern) (eq? (car pattern) '?v) false))

(define (variable-name pattern) (cadr pattern))

;; Skeletons & Evaluations

(define (skeleton-evaluation?    skeleton)
  (if (pair? skeleton) (eq? (car skeleton) ':) false))

(define (evaluation-expression evaluation) (cadr evaluation))


;; Evaluate (dangerous magic)

(define (evaluate form dictionary)
  (if (atom? form)
      (lookup form dictionary)
      (apply (eval (lookup (car form) dictionary)
                   user-initial-environment)
             (mapcar (lambda (v) (lookup v dictionary))
                     (cdr form)))))

;;
;; A couple sample rule databases...
;;

;; Algebraic simplification

(define algebra-rules
  '(
    ( ((? op) (?c c1) (?c c2))                (: (op c1 c2))                )
    ( ((? op) (?  e ) (?c c ))                ((: op) (: c) (: e))          )
    ( (+ 0 (? e))                             (: e)                         )
    ( (* 1 (? e))                             (: e)                         )
    ( (* 0 (? e))                             0                             )
    ( (* (?c c1) (* (?c c2) (? e )))          (* (: (* c1 c2)) (: e))       )
    ( (* (?  e1) (* (?c c ) (? e2)))          (* (: c ) (* (: e1) (: e2)))  )
    ( (* (* (? e1) (? e2)) (? e3))            (* (: e1) (* (: e2) (: e3)))  )
    ( (+ (?c c1) (+ (?c c2) (? e )))          (+ (: (+ c1 c2)) (: e))       )
    ( (+ (?  e1) (+ (?c c ) (? e2)))          (+ (: c ) (+ (: e1) (: e2)))  )
    ( (+ (+ (? e1) (? e2)) (? e3))            (+ (: e1) (+ (: e2) (: e3)))  )
    ( (+ (* (?c c1) (? e)) (* (?c c2) (? e))) (* (: (+ c1 c2)) (: e))       )
    ( (* (? e1) (+ (? e2) (? e3)))            (+ (* (: e1) (: e2))
                                                 (* (: e1) (: e3)))         )
    ))

(define algsimp (simplifier algebra-rules))

;; Symbolic Differentiation

(define deriv-rules
  '(
    ( (dd (?c c) (? v))              0                                 )
    ( (dd (?v v) (? v))              1                                 )
    ( (dd (?v u) (? v))              0                                 )
    ( (dd (+ (? x1) (? x2)) (? v))   (+ (dd (: x1) (: v))
                                        (dd (: x2) (: v)))             )
    ( (dd (* (? x1) (? x2)) (? v))   (+ (* (: x1) (dd (: x2) (: v)))
                                        (* (dd (: x1) (: v)) (: x2)))  )
    ( (dd (** (? x) (?c n)) (? v))   (* (* (: n) (+ (: x) (: (- n 1))))
                                        (dd (: x) (: v)))              )
    ))

(define dsimp (simplifier deriv-rules))

(define scheme-rules
  '(( (square (?c n)) (: (* n n)) )
    ( (fact 0) 1 )
    ( (fact (?c n)) (* (: n) (fact (: (- n 1)))) )
    ( (fib 0) 0 )
    ( (fib 1) 1 )
    ( (fib (?c n)) (+ (fib (: (- n 1)))
                      (fib (: (- n 2)))) )
    ( ((? op) (?c e1) (?c e2)) (: (op e1 e2)) ) ))

(define scheme-evaluator (simplifier scheme-rules))

DrRacket で R5RS を使用して実行していますが、最初に遭遇した問題はそのアトムでしたか? 未定義の識別子でした。そのため、次を追加できることがわかりました。

    (define (atom? x) ; atom? is not in a pair or null (empty)
    (and (not (pair? x))
    (not (null? x))))

次に、この獣を実際に実行する方法を理解しようとしたので、ビデオをもう一度見て、彼が次のように使用しているのを見ました。

(dsimp '(dd (+ x y) x))

Sussman が述べたように、(+ 1 0) に戻る必要があります。代わりに、R5RS を使用すると、次の行で拡張辞書プロシージャが壊れているようです。

((eq? (cadr v) dat) dictionary) 

返される特定のエラーは次のとおりです。 mcdr: 可変ペア型の引数が必要です。与えられた #f

neil/sicp を使用する場合、次の行で評価手順を中断しています。

(apply (eval (lookup (car form) dictionary)
                   user-initial-environment)

返される特定のエラーは次のとおりです: モジュール内のバインドされていない識別子: ユーザー初期環境

以上のことを踏まえて、私は何らかの助け、または正しい方向への良いナッジをいただければ幸いです。ありがとう!

4

3 に答える 3

15

コードは 1991 年のものです。R5RS は 1998 年に登場したため、コードは R4RS (またはそれ以前) 用に作成する必要があります。R4RS とそれ以降のスキームの違いの 1 つは、空リストが R4RS では false と解釈され、R5RS では true と解釈されたことです。

例:

  (if '() 1 2)

R5RS では 1 を返しますが、R4RS では 2 を返します。

したがって、assq などのプロシージャは、false ではなく '() を返す可能性があります。これが、extend-directory の定義を次のように変更する必要がある理由です。

(define (extend-dictionary pat dat dictionary)
  (let ((vname (variable-name pat)))
    (let ((v (assq vname dictionary)))
      (cond ((not v)
             (cons (list vname dat) dictionary))
            ((eq? (cadr v) dat) dictionary)
            (else 'failed)))))

また、当時、地図は mapcar と呼ばれていました。mapcar を map に置き換えるだけです。

DrRacket で表示されたエラーは次のとおりです。

mcdr: expects argument of type <mutable-pair>; given '()

これは、cdr が空のリストを取得したことを意味します。空のリストには cdr がないため、エラー メッセージが表示されます。現在、DrRacket は cdr の代わりに mcdr を書き込みますが、今は無視してください。

最善のアドバイス: 一度に 1 つの関数を実行し、REPL でいくつかの式を使用してテストします。これは、すべてを一度に理解するよりも簡単です。

最後に、プログラムを次のように開始します。

(define user-initial-environment (scheme-report-environment 5))

R4RS (または 1991 年の MIT スキーム?) からの別の変更。

補遺:

このコードhttp://pages.cs.brandeis.edu/~mairson/Courses/cs21b/sym-diff.scmはほとんど実行されます。DrRacket で次のプレフィックスを付けます。

#lang r5rs
(define false #f)
(define user-initial-environment (scheme-report-environment 5))
(define mapcar map)

そして、extend-directory で (null? v) を (not v) に変更します。これは、少なくとも単純な式では機能します。

于 2011-08-07T22:44:56.497 に答える
1

これがmit-scheme(リリース9.1.1)で機能するコードです

于 2012-07-01T19:01:57.197 に答える
1

このコードを使用することもできます。ラケットで動作します。

エラーなしで「eval」を実行するには、以下を追加する必要がありました

(define ns (make-base-namespace))
(apply (eval '+ ns) '(1 2 3))
于 2012-07-11T19:43:03.453 に答える