【问题标题】:sicp pattern matching - compound?scp 模式匹配 - 复合?
【发布时间】:2015-01-27 03:18:02
【问题描述】:

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

到目前为止,我发现 Matcher 和 Instantiator 很简单。但我无法进入简化器。

(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)

我在这里看到了关于这个主题的另一个问题,它根据pair? 定义了compound?。但是,那simplify-exp 喂给try-rules 什么呢?

【问题讨论】:

  • 您使用的是球拍还是计划?问题标记为scheme,但您的代码以#lang racket 开头。它们是相似语言,但它们并不相同。在 Scheme 和许多 Lisps 中,空列表 是 一个原子,因此 ((null? s) '())(您在答案中添加的内容)在 ((atom ?s) s) 之后是多余的。

标签: scheme racket sicp


【解决方案1】:

想通了。这些规则将按照承诺适用于每个节点。您可以投票删除问题。但是,我会添加一些关于我如何使它工作的解释。

我更改了一些代码。原始代码似乎是在考虑其他语义的情况下编写的。我添加了一些评论,我自己做出了一些决定。

#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 和许多 Lisps 中,空列表 是 一个原子,所以 ((null? s) '()) 在 ((atom ?s) s) 之后是多余的。问题标记为scheme,但您的代码以#lang racket 开头。它们是相似的语言,但并不相同。
  • @JoshuaTaylor,我正在使用 DrRacket。 mit-scheme 对我来说感觉不太好。谢谢你的评论。让一切都清楚。事实上我定义了atom?,但我认为'()不应该是一个原子。
  • @JoshuaTaylor Racket 是每个 tag-wiki 的方案。它也是一个 Lisp。
  • @benrudgers Racket 是一种与 Scheme 有许多相似之处的语言,并且源自 Scheme,但并非所有适用于 Scheme 的东西都适用于 Racket。不同的 Lisp 也存在差异。例如,在包括 Common Lisp 在内的许多传统 Lisp 中,空列表与符号 NIL 相同,是假值。在 Scheme 中,只有实际的布尔值 #f 为 false。 OP 提到“原始代码似乎是在考虑其他语义的情况下编写的”,对代码所做的更改之一是在 cond 之前的 (null? s) 中添加 (atom? s)。在许多 Lisp 中,……
  • @benrudgers ...(可能包括 Racket 和 Scheme;我不确定 OP 的所有更改是否真的有必要)(null? s) 将是多余的,因为空列表 is 一个原子。似乎有一种趋势(可能是由于教师)说他们使用的是 Scheme,但实际上使用的是 Racket。很多代码都可以在这两个地方工作,但不是所有的代码。例如,Racket 现在默认使用不可变的 cons-cells,所以在 Scheme 中你可以(set-car! (cons a b) c),但在 Racket 中你不能。我不认为问OP实际使用什么编程语言是不合理的……
猜你喜欢
  • 2016-11-02
  • 2015-09-30
  • 1970-01-01
  • 2019-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-27
相关资源
最近更新 更多