Scheme sicp模式匹配-复合?

Scheme sicp模式匹配-复合?,scheme,racket,sicp,Scheme,Racket,Sicp,我正在看SICP的视频讲座。目前我从事4A模式匹配和基于规则的替换 到目前为止,我发现Matcher和实例化器都很简单。但是我不能让我的头脑简单化 (define (simplifier the-rules) (define (simplify-exp exp) (try-rules (if (compound? exp) (map simplify-exp exp) exp))) (define (tr

我正在看SICP的视频讲座。目前我从事4A模式匹配和基于规则的替换

到目前为止,我发现Matcher和实例化器都很简单。但是我不能让我的头脑简单化

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

我在这里看到了关于这个主题的另一个问题,它定义了
复合物?
,即
成对物?
。但是,然后什么
简化exp
馈送到
try rules

解决了这个问题。这些规则将按照承诺应用于每个节点。你可以投票删除该问题。但是,我想补充一些关于我是如何使它工作的解释

我更改了一些代码。原始代码似乎在编写时考虑了其他一些语义。我在自己做决定的地方添加了一些评论

#lang racket
;matcher
(define (match pat exp dict)
  (cond ((eq? dict 'failed) 'failed)
        ;matched
        ((and (null? pat) (null? exp)) dict)
        ;so far matched, but no more
        ((or (null? pat) (null? exp)) 'failed)
        ((atom? pat)
         (if (atom? exp)
             (if (eq? pat exp)
                 dict
                 'failed)
             'failed))
        ((pat-const? pat)
         (if (constant? exp)
             (extend-dict pat exp dict)
             'failed))
        ((pat-variable? pat)
         (if (variable? exp)
             (extend-dict pat exp dict)
             'failed))
        ((pat-exp? pat)
             (extend-dict pat exp dict))
        ((atom? exp) 'failed)
        (else
         (match (cdr pat)
                (cdr exp)
                (match (car pat) (car exp) dict)))))
(define (pat-const? pat)
  (eq? (car pat) '?c))
(define (pat-variable? pat)
  (eq? (car pat) '?v))
(define (pat-exp? pat)
  (eq? (car pat) '?))
(define constant? number?)
(define variable? symbol?)
;instantiator
(define (instantiate skeleton dict)
  (define (loop s)
    (cond ((atom? s) s)
          ;we cant run past the nil line
          ((null? s) '())
          ((skeleton-evaluation? s) (evaluate s dict))
          (else
           (cons (loop (car s)) (loop (cdr s))))))
  (loop skeleton))

(define (skeleton-evaluation? s)
  (eq? (car s) ':))
;made it simpler, no environment constant, sorry
(define (evaluate s dict)
  (let ((data (lookup (cadr s) dict)))
    (if (null? data)
        (display "error in rules. mismatch")
        (cadr data))))
;simplifier
(define (simplifier rules)
  (define (simplify-exp exp)
    (try-rules (if (list? exp)
                   (map simplify-exp exp)
                   exp)))
  (define (try-rules exp)
    (define (scan rule)
      (if (null? rule)
          exp
          (let ((dict (match (pattern (car rule)) exp (empty-dict))))
              (if (eq? dict 'failed)
                  (scan (cdr rule))
                  (simplify-exp (instantiate (skeleton (car rule)) dict))))))
    (scan rules))
  simplify-exp)

(define pattern car)
(define skeleton cadr)

;dictionary
(define (empty-dict)
  '())
(define (extend-dict pat exp dict)
  (let ((v (lookup (cadr pat) dict)))
    (if (null? v)
        (cons (list (cadr pat) exp) dict)
        (if (eq? (cadr v) exp)
            dict
            'failed))))
(define (lookup s dict)
  (cond ((null? dict) '())
        ((eq? (caar dict) s) (car dict))
        (else (lookup s (cdr dict)))))


;extend racket
(define (atom? a)
  (and (not (null? a)) (not (pair? a))))

然后呢?你知道吗?它能用。
:)

你用的是球拍还是诡计?在Scheme和许多Lisp中,空列表是一个atom,因此
((null?s)())
((atom?s)
之后是冗余的。问题标记为,但您的代码以
#lang racket
开头。它们是相似的语言,但它们不一样。@JoshuaTaylor,我在用DrRacket。我觉得麻省理工学院的计划不太好。谢谢你的评论。一切都清楚了。事实上,我定义了
atom?
,但我认为
'()
不应该是一个atom。@JoshuaTaylor Racket是每个标记wiki的一个方案。它也是一种口齿不清的语言。@benrudgers Racket是一种与Scheme有许多相似之处并从Scheme继承而来的语言,但并不是所有适用于Scheme的语言都适用于Racket。不同的Lisp也有不同之处。例如,在许多传统的Lisp(包括Common Lisp)中,空列表与符号NIL相同,是假值。在Scheme中,只有实际的布尔值#f为false。OP提到“原始代码似乎是在考虑其他语义的情况下编写的”,对代码所做的更改之一是在
(null?s)
之前的
条件中添加
(atom?s)
。在许多Lisp中,@benrudgers…(可能包括Racket和Scheme;我不确定OP的所有更改是否都是必要的)
(null?s)
将是多余的,因为空列表是一个原子。似乎有一种趋势,人们(可能是因为教练)说他们在使用诡计,但实际上在使用球拍。很多代码可以在这两个地方工作,但不是所有的代码。例如,Racket现在默认使用不可变的cons单元格,因此在Scheme in中您可以
(设置car!(cons a b)c)
,但在Racket中您不能。我不认为问OP实际上使用的是什么编程语言是不合理的……你是在使用racket还是scheme?问题标记为,但您的代码以
#lang racket
开头。它们是相似的语言,但它们不一样。在Scheme和许多Lisp中,空列表是一个atom,因此
((null?s)())
(您在答案中添加的内容)在
((atom?s)s)
之后是多余的。