Metacircular Evaluator与分析(Metacircular)评估员的区别

时间:2016-01-28 17:12:55

标签: scheme sicp

section 4.1 of the Structure and Interpretation of Computer Programs中,引入了两位评估员,即元外评估员和分析元外评估员。

完整的元叶评估员可以在这里找到: https://mitpress.mit.edu/sicp/code/ch4.scm

可以在此处找到完整的元外评估器和分析: https://mitpress.mit.edu/sicp/code/ch4-analyzingmceval.scm

现在,两者之间的区别在于分析评估者eval具有分析表达式的分析方法。

(define (eval exp env)
  ((analyze exp) env))

(define (analyze exp)
  (cond ((self-evaluating? exp) 
         (analyze-self-evaluating exp))
        ((quoted? exp) (analyze-quoted exp))
        (...)

分析程序的例子如下:

(define (analyze-self-evaluating exp)
  (lambda (env) exp))

或者这个:

(define (analyze-quoted exp)
  (let ((qval (text-of-quotation exp)))
    (lambda (env) qval)))

而metacircular评估员eval这样做:

(define (eval exp env)
  (cond ((self-evaluating? exp) exp)
  (...)

(define (text-of-quotation exp) (cadr exp))

我期望分析评估者做的是在环境中的某个地方缓存先前分析的结果,但我没有看到这一点。我看不出分析评估员到底做了什么。

那么,分析评估者究竟做了什么,为什么它会使评估者加速一点点呢?

1 个答案:

答案 0 :(得分:1)

如果你注意analyze-something函数,你会看到它们中的每一个(部分analyze-self-evaluatinganalyze-variables)执行一些操作,然后返回{{ 1}}。例如:

lambda

在另一个翻译中,我们有:

(define (analyze-if exp)
  (let ((pproc (analyze (if-predicate exp)))
        (cproc (analyze (if-consequent exp)))
        (aproc (analyze (if-alternative exp))))
    (lambda (env)
      (if (true? (pproc env))
          (cproc env)
          (aproc env)))))

这里发生了什么?在第二种情况下,每次计算相同的表达式时(例如因为我们多次执行递归函数的主体),在表达式上调用(define (eval-if exp env) (if (true? (eval (if-predicate exp) env)) (eval (if-consequent exp) env) (eval (if-alternative exp) env))) 版本,然后再次计算所有内容,包括eval-something对应物在返回函数之前执行的内容!

在第一种情况下,分析函数的第一部分只执行一次,多次执行的是它返回的过程。

如果您特别考虑analyzing-something案例,这一点应该很清楚。比较两个函数:

definition

(define (analyze-definition exp)
  (let ((var (definition-variable exp))
        (vproc (analyze (definition-value exp))))
    (lambda (env)
      (define-variable! var (vproc env) env)
      'ok)))

在第二个函数中,函数在(define (eval-definition exp env) (define-variable! (definition-variable exp) (eval (definition-value exp) env) env) 'ok) 内调用{/ 1}} 每个时间的形式评估:

(definition-value exp)

在第一种情况下,您可以看到在函数的eval部分调用了... ((definition? exp) (eval-definition exp env)) ... ,然后将其结果存储到var,因此不再评估它。