【问题标题】:What is Classifier and Transformer in MIT Scheme?MIT 方案中的分类器和变压器是什么?
【发布时间】:2022-01-07 18:02:42
【问题描述】:

在以下方案代码中,accumulate 进行右折叠。当我尝试使用 mit 方案运行时。我遇到了以下错误:

Transformer may not be used as an expression: #[classifier-item 13]
Classifier may not be used as an expression: #[classifier-item 12]

我用谷歌搜索但没有找到有用的信息。和宏有关吗?

; This function is copied from SICP chapter 2
(define (accumulate op initial sequence)
  (if (null? sequence)
      initial
      (op (car sequence)
          (accumulate op initial (cdr sequence)))))

; works as expected
(accumulate
   (lambda (x y) (or x y))  ; replace or with and also works
   #f
   '(#t #f #t #f #f)
))

; does not work
; error: Classifier may not be used as an expression: #[classifier-item 12]
(accumulate
   or
   #f
   '(#t #f #t #f #f)
))

; does not work
; error: Transformer may not be used as an expression: #[classifier-item 13]
(accumulate
   and
   #f
   '(#t #f #t #f #f)
))

【问题讨论】:

  • 作为一个疯狂的猜测,或者和和是不能像函数名一样传递的语法元素。
  • 这些似乎是(未记录的?)麻省理工学院方案特有的术语。问题是orand 是特殊形式,而不是过程。
  • 感谢@molbdnilo,这很好。
  • 分类器是句法分析的一部分,它决定表达式的类型(定义、lambda 主体、表达式等)。变压器是宏观系统的一部分,这很困难。

标签: scheme lisp


【解决方案1】:

宏可以在某些语言中传递,但不能在 Scheme 和 Common Lisp 中传递。原因是宏应该能够提前扩展。例如。

(define (cmp a b)
  (cond ((< a b) -1)
        ((> a b) 1)
        (else 0)))

现在编译方案将递归扩展每个节点,用扩展替换它,直到它没有变化:

(define (cmp a b)
  (if (< a b) 
      (begin -1)
      (cond ((> a b) 1)
            (else 0))))

(define (cmp a b)
  (if (< a b) 
      -1
      (cond ((> a b) 1)
            (else 0))))

(define (cmp a b)
  (if (< a b) 
      -1
      (if (> a b) 
          (begin 1)
          (cond (else 0)))))

(define (cmp a b)
  (if (< a b) 
      -1
      (if (> a b) 
          1
          (cond (else 0)))))

; end result
(define (cmp a b)
  (if (< a b) 
      -1
      (if (> a b) 
          1
          0)))

cond 的这一点来看,根本不需要存在于底层语言中,因为你永远不会使用它,但是如何实现它才能工作:

(define (test syntax a b)
  (syntax a b))

(test or #f #t)

为此,底层语言需要知道 or 在扩展之后是什么,因为 syntax 需要绑定到 or 然后才能发生转换。但是当代码运行时,宏扩展已经发生,并且在大多数实现中,您会看到一些表明or 是未绑定变量的内容。似乎 MIT Scheme 已经为顶级语法语法添加了错误检查,如果你不覆盖它就会触发错误。例如。如果你添加这个,你不会看到任何问题:

(定义(或 a b)(如果 a a b)) (define (and a b) (if a b #f))

现在在这些行之后,任何对andor 的引用都不是语法,而是这些过程。 Scheme 中没有保留字,所以如果你做了一些疯狂的事情,比如定义 define,你就不能在该范围的其余部分使用它:

(define define display) ; defiens define as a top level variable
(define define)  ; prints the representation of the function display
(define test 10) ; fail since test is an undefined variable so it cannot be displayed. 

我用实际上可以传递的宏创建了一个解释型 lisp,但它不是很有用,而且优化的机会也大大降低了。

【讨论】:

    【解决方案2】:

    是的,它与 andor 等宏/特殊形式有关。

    您可以简单地将它们包装为 lambda,(accumulate (lambda (a b) (or a b)) ...) 来使其工作——结果将是正确的,但当然不会有任何短路。 op 是一个函数,函数接收其参数已经评估。

    要么隐藏 lambdas ((lambda () ...)) 后面的参数并根据需要手动评估它们,要么为每个宏 op 定义特定版本,例如

    (define (accumulate-or initial sequence)
      (if (null? sequence)
          initial
          (or (car sequence)
              (accumulate-or initial (cdr sequence)))))
    

    这里的sequence 仍将在调用accumulate-or 之前进行全面评估,但至少accumulate-or 即使在结果已知之后也不会通过它。

    如果sequence 包含一些您希望避免的繁重计算结果以防不需要,请考虑为此使用“惰性序列”。

    【讨论】:

    • 这两个答案都没有提供问题的答案。 “分类器”和“变压器”的起源来自麻省理工学院的 AI-memo,我认为与 memo 1049 有关但不确定。你的回答就像评论一样——我做了很多次。
    猜你喜欢
    • 2017-02-19
    • 1970-01-01
    • 1970-01-01
    • 2023-02-18
    • 2021-11-05
    • 2015-05-09
    • 1970-01-01
    • 2023-03-23
    • 2014-04-03
    相关资源
    最近更新 更多