Michele,
The distinction you make between "compiler semantics" and
"interpreter semantics" is not accurate. Allow me to explain.
Compiler semantics (aka phased semantics) means that a piece of code
is processed in two steps: first, it is fully expanded yielding code
with no macro definitions and macro uses, *then* the resulting code
is evaluated (using an interpreter, compiler, or whatever).
Interpreter semantics (aka unphased semantics) means that expansion
and evaluation happen simultaneously, or more accurately, expansion
and evaluation steps are interleaved.
The examples you give in the article, and all the systems you compare
follow the phased semantics, and I have not seen any Scheme systems
that still uses interpreter semantics (with the exception of SCM
maybe but I haven't used it so I can't say much about it). So, how
do these systems (Ypsilon, Ikarus, and PLT) differ? And how does the
Ikarus/Ypsilon REPL differ from the R6RS-script mode?
It's the granularity, or size of the compilation unit that makes the
difference between the repl and the script modes. In the repl, the
compilation unit is one single expression or definition entered into
the repl. That unit is expanded, then evaluated, and the result is
printed to the console (or saved in case of definitions) before the
repl accepts a new expression. In case of scripts, the whole program
is first expanded then evaluated as a whole unit.
In your example, you have a procedure definition:
(define (distinct? eq? ls) ---)
and a syntax definition that uses it:
(def-syntax (assert-distinct arg ...) --- distinct? ---)
In phased semantics, you want the definition of distinct? to be
available (already processed, evaluated, whatever) *before* it is
used in the syntax definition, so, it has to be in a separate
compilation unit. In the Ikarus/Ypsilon repl, it is sufficient to
enter the first definition into the repl to have it available for
syntax definitions. In a script (a whole compilation unit), you
cannot do that, so you define distinct? in a separate compilation
unit (a library) to get around the limitation.
Now compiler and interpreter semantics as described above differ when
you try to do:
(let ()
(define (distinct? eq? ls) ---)
(def-syntax (assert-distinct arg ...) --- distinct? ---)
---)
or even a simpler one:
(let ()
(define var 12)
(define-syntax syn (lambda (hukarez) var))
(syn))
Here, the whole let expression is a single compilation unit. So,
regardless of whether you enter it into the repl, or have it in a
script, a system that uses compiler/phased semantics is going to
reject it (with an "identifier out of context" error), and a system
that uses interpreter semantics is going to accept it just fine.
The reason why I'm making this distinction is because the conclusion
of the article says (among other things) that "In such [interpreter]
semantics everything happens at runtime, and there is no phase
separation at all". While the statement is true, none of the systems
discussed in the article uses interpreter semantics where everything
happens at run time and there is no phase separation at all.
Makes sense? No?
Aziz,,,
[PS. Posting to the list since I thought this is probably useful
information for everybody. I usually try to keep my comments private.]
On Apr 25, 2009, at 8:14 AM, Michele Simionato wrote:
Just for the people in this list:
http://www.phyast.pitt.edu/~micheles/scheme/scheme20.html
This episode - as well as all the episodes about the module system -
are based on the help I got from this list, so if I am presenting
your words incorrectly, please do chastize me.