[racket] a syntax-case question
Jon Stenerson wrote:
> I'm trying to understand what this is supposed to do:
> (define (parse stx)
> (syntax-case stx ()
> [(_ p ...) #'(p ...)]))
> (display (parse #'(1 2 3)))
Are you interested only in the difference between the
results in different languages or also in the actual
operations performed by SYNTAX-CASE?
> If I run this in DrRacket with first line #lang racket I
> get a syntax object containing a list: #<syntax:7:17 (2
> 3)>
If I run the code as a script from a terminal (in
GNU+Linux) I get:
{#<syntax:/home/marco/var/tmp/proof.sps:11:21 2>
#<syntax:/home/marco/var/tmp/proof.sps:11:23 3>}
> Is this a legitimate difference between two languages? Or
> is one of them right and the other wrong?
Both representations are valid. When the return value is
a single syntax object holding a list, it is called "wrapped
syntax object"; when the return value is a list of syntax
objects it is called "unwrapped syntax object" or simply
"syntax object".[1]
We can think of a wrapped syntax object as an instance of
the record type SYNTAX-OBJECT, which is usually not exposed
in the public API of a Scheme language implementation, while
an unwrapped syntax object is a compound value holding at
least one instance of the record type SYNTAX-OBJECT and no
Scheme symbols outside of SYNTAX-OBJECT records.
It is always possible to unwrap a wrapped syntax object to
produce an (almost) equivalent fully unwrapped syntax
object. In general, the two representations:
#<syntax:(2 3)>
(#<syntax:2> #<syntax:3>)
hold the same informations with respect to what is needed to
produce the output form of a macro, but the wrapped syntax
object may hold "better" meta-informations, like the source
location of the list it holds.
Notice that in this specific case the syntax object holds
only number values, so it would have been perfectly legal to
just return a plain list:
(2 3)
because, for the purpose of completing the macro expansions,
no lexical informations need to be attached to datum values;
strictly speaking, only identifiers need lexical
informations.
Stripping the context from a list of numbers has at least
two effects:
* Meta-informations (like source code location) are lost.
* The stripped value cannot be used as first argument to the
function DATUM->SYNTAX, which is sometimes useful. Racket
allows this in non-R6RS languages, R6RS requires the first
argument to be an identifier.
Wrapped syntax objects can sometimes be more memory
efficient and they can sometimes be handled in a more
efficient way (requiring less operations to be dealt with);
but while the expander completes its work: sooner or later
it will fully unwrap all the syntax objects it needs to
produce an output form.
You may be interested in reading my dirty and ugly
introduction for beginner users of SYNTAX-CASE[2].
HTH
[1] <http://marcomaggi.github.com/docs/nausicaa.html/stdlib-syntax_002dcase-objects.html>
[2] <http://marcomaggi.github.com/docs/nausicaa.html/stdlib-syntax_002dcase-intro.html>
--
Marco Maggi