5

In SICP Chapter 4, the metacircular evaluator is modified by separating the syntax analysis from the execution, making the eval procedure look like:

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

and the book says that this will save work since analyze will be called once on an expression, while the execution procedure may be called many times.

My question is, how does this optimization work? It will work for recursive procedure calls, but how about other cases? The evaluator evaluates expressions one after another, eval will still be called on each expression even if they have identical forms.

pjhades
  • 1,948
  • 2
  • 19
  • 34

3 Answers3

5

You need to see several things: (a) the analyze function walks over each expression exactly once, (b) there is no code outside of analyze that scans the syntax, (c) the function that analyze returns does not call itself therefore running that function never leads to any further scanning of the syntax, (d) this is all unlike the usual evaluation functions where calling a function twice means that its syntax is scanned twice.

BTW, a much better name for analyze is compile -- it really does translate the input language (sexprs) to a target one (a function, acting as the machine code here).

John Clements
  • 16,895
  • 3
  • 37
  • 52
Eli Barzilay
  • 29,301
  • 3
  • 67
  • 110
  • Thanks for your answer first:) Does this optimization only makes sense in cases of recursive calls? If I have a procedure `(define (loop) (loop))`, then `(loop)` won't be analyzed for each recursive call. But if I have two identical `if` forms then each of them will be analyzed when we call `eval` on them. Maybe I got something wrong when trying to understand this point. – pjhades Feb 06 '12 at 07:50
  • It applies whenever a function is called more than once, saving on the scan that would have been done on the second call etc. But these are of course not so important, it's only with recursive functions that the difference really makes sense. But "only" is an understatement, since recursion is basically the same as looping -- no recursion is the same as no looping, and in such a world there's no point for compilation at all. – Eli Barzilay Feb 06 '12 at 08:31
2

The difference between a compiler and a interpreter is that:

A compiler scan your source code only once and change it into to execution code (machine code maybe). When you execute your program the next time, you directly execute the execution code without analyzing the source code, which is efficient.

A interpreter, however, analyze the source code each time you execute your program.

This optimization only makes sense in cases of your program will be executed more than once.

As @Eli Barzilay said, "a much better name for analyze is compile", your analyzed functions is like the execution code. The recursive functions are like programs which would be executed more than once.

Nmzzz
  • 2,462
  • 3
  • 19
  • 18
1

analyze just does syntax analyses once and store the transformed definition and so on in the environment which may be used through lookup-variable-value directly when the related procedure is executed.

In contrast, the original metacircular evaluator twists the syntax analysis and execution which makes each execution invokes syntax analysis as well.

This link maybe helpful: http://www.cs.brandeis.edu/~mairson/Courses/cs21b/Handouts/feeley-notes.pdf

Kamel
  • 1,856
  • 1
  • 15
  • 25