什么是 MIT Scheme 中的分类器和转换器?

What is Classifier and Transformer in MIT Scheme?

提问人:Xiaoyong Guo 提问时间:1/8/2022 最后编辑:alinsoarXiaoyong Guo 更新时间:1/9/2022 访问量:226

问:

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

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)
))
LISP 方案

评论

2赞 Shawn 1/8/2022
作为一个疯狂的猜测,or 和 and 是不能像函数名称一样传递的语法元素。
1赞 molbdnilo 1/8/2022
这些似乎是麻省理工学院特有的(未记录的?)术语。问题在于,和是特殊形式,而不是程序。orand
0赞 Xiaoyong Guo 1/8/2022
谢谢@molbdnilo,这很好。
0赞 alinsoar 1/9/2022
分类器是语法分析的一部分,用于确定表达式的类型(定义、lambda 正文、表达式等)。变压器是宏系统的一部分,这很困难。

答:

1赞 Will Ness 1/9/2022 #1

是的,它与宏/特殊形式有关,例如 和 .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)))))

在调用 之前,这里仍将进行全面评估,但至少即使在结果已知之后也不会完成它。sequenceaccumulate-oraccumulate-or

如果包含一些繁重的计算结果,你想避免这些结果,以防万一,可以考虑使用“惰性序列”。sequence

评论

1赞 alinsoar 1/13/2022
这两个答案都没有提供问题的答案。“分类器”和“转换器”的起源来自麻省理工学院的 AI 备忘录,我认为与备忘录 1049 有关,但不确定。你的回答就像一个评论——我做了很多次相同的。
2赞 Sylwester 1/9/2022 #2

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

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

现在,编译 Scheme 将递归地扩展每个节点,将其替换为扩展,直到它没有变化:

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

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

(定义(或 b)(如果 a a b)) (定义(和 b)(如果 a b #f))

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

(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,它实际上可以传递,但它不是很有用,优化的机会大大降低。