Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

porting from Ikarus to PLT

78 views
Skip to first unread message

Michele Simionato

unread,
Oct 26, 2008, 6:46:49 AM10/26/08
to
I was trying to port a R6RS library of mine from Ikarus to mzscheme,
but I get the following error:

compile: unbound variable in module (in the transformer environment,
which does not include the macro definition that is visible to run-
time expressions)

Do you know what does it mean? I am defining a helper macro to define
transformers. I wonder if I am accidentally relying on features
specific to Ikarus, if it is issue related to phase separation, or
what else :-(

For the curious, the code is here:
https://www.phyast.pitt.edu/~micheles/scheme/sweet-macros.sls

Abdulaziz Ghuloum

unread,
Oct 26, 2008, 11:28:40 AM10/26/08
to
Michele Simionato wrote:

> Do you know what does it mean? I am defining a helper macro to define
> transformers. I wonder if I am accidentally relying on features
> specific to Ikarus, if it is issue related to phase separation, or
> what else :-(

MzScheme does not like it if you do:

(define-syntax foo (lambda (stx) ---))

(define-syntax bar (lambda (stx) --- foo ---))

while Ikarus allows it. Ikarus says: hey, we have the transformer,
so, we might as well make it available. MzScheme says: hey, if you
can't access run-time variables, then you can't access run-time
macros either.

To make it work under MzScheme, you have to split this library into
two (or maybe more) libraries, and add the "import for" clauses that
make MzScheme happy.

Aziz,,,

Michele Simionato

unread,
Oct 28, 2008, 2:53:18 AM10/28/08
to
On Oct 26, 4:28 pm, Abdulaziz Ghuloum said:
> MzScheme does not like it if you do:
>
> (define-syntax foo (lambda (stx) ---))
>
> (define-syntax bar (lambda (stx) --- foo ---))
>
> while Ikarus allows it.  Ikarus says: hey, we have the transformer,
> so, we might as well make it available.  MzScheme says: hey, if you
> can't access run-time variables, then you can't access run-time
> macros either.
>
> To make it work under MzScheme, you have to split this library into
> two (or maybe more) libraries, and add the "import for" clauses that
> make MzScheme happy.
>
> Aziz,,,

Damn, this is the answer I did not want to hear!
Anyway, it seems I can get it to work by following the examples in
http://www.r6rs.org/final/html/r6rs/r6rs-Z-H-10.html#node_sec_7.2 .

I am still curious, though. I would like to understand the technical
reason why Ikarus is able to recognize the helper macro without
forcing me to put it in another module, whereas mzscheme cannot. It
seems that in Ikarus can go away without
the (import (for (module) expand)) trick, but why it is so?
I suppose the difference to be somewhat related to the fact that
Ikarus is an incremental compiler whereas mzscheme is a batch
compiler, but I must admit that this point is quite foggy to me.
Care to explain?

Michele Simionato

Jens Axel Soegaard

unread,
Oct 28, 2008, 5:20:10 AM10/28/08
to
Michele Simionato wrote:
> On Oct 26, 4:28 pm, Abdulaziz Ghuloum said:
>> MzScheme does not like it if you do:
>>
>> (define-syntax foo (lambda (stx) ---))
>>
>> (define-syntax bar (lambda (stx) --- foo ---))
>>
>> while Ikarus allows it. Ikarus says: hey, we have the transformer,
>> so, we might as well make it available. MzScheme says: hey, if you
>> can't access run-time variables, then you can't access run-time
>> macros either.
>>
>> To make it work under MzScheme, you have to split this library into
>> two (or maybe more) libraries, and add the "import for" clauses that
>> make MzScheme happy.

Michele: Does mzscheme in your post mean R6RS language of mzscheme?
If not, I think you can use:

(define-for-syntax foo (lambda (stx) ---))


(define-syntax bar (lambda (stx) --- foo ---))

However, if you need a full explanation, send a post to the PLT
mailing list in order for Flatt to see the question.

--
Jens Axel Søgaard

Jens Axel Soegaard

unread,
Oct 28, 2008, 6:44:42 AM10/28/08
to


What happens in the following situation:

Library A:

(define-syntax foo (lambda (stx) ---1))


Library B imports A:

(define-syntax foo (lambda (stx) ---2))

(define-syntax bar (lambda (stx) --- foo ---))

Will PLT and Ikarus behave the same here?

--
Jens Axel Søgaard

Michele Simionato

unread,
Oct 28, 2008, 2:13:38 PM10/28/08
to
On Oct 28, 10:20 am, Jens Axel Soegaard wrote:
> Michele: Does mzscheme in your post mean R6RS language of mzscheme?

Yes, I am running

$ plt-r6rs --install sweet-macros.sls

and I have already posted the code I want to port:

http://www.phyast.pitt.edu/~micheles/scheme/sweet-macros.sls

This morning I did some experiment with a simplified version
of the code, by putting many libraries in the same file and using
(import for expand) and it worked, but I cannot get the real code to
compile now. I cannot work on it this evening, so I will leave it for
tomorrow. If somebody who is familiar with the PLT build system wants
to try, you are welcome: the module contains only fifty lines and four
macros, no helper functions at all, so it should not be a big deal.

Michele Simionato

unread,
Oct 28, 2008, 2:36:56 PM10/28/08
to
BTW, I did write a version of sweet-macros for Chicken, and I run it
in the interpreter without issues, but I did not make an egg. If
somebody wants to make an egg of it, help would be appreciated. Here
it is http://www.phyast.pitt.edu/~micheles/scheme/sweet-macros.scm.

I also run the Ikarus version on ypsilon, but it did not
work due to a bug in the recognition of patterns of the form (...
xxx). Actually Aziz found a workaround by replacing each ...
with (... ...), but it would be best if the bug was fixed.
I will send a bug report to the tracket tomorrow.

This code is for a good cause, to divulgate Scheme to the masses, so
feel free to help ;)

M. Simionato

Michele Simionato

unread,
Oct 30, 2008, 2:10:01 AM10/30/08
to
On Oct 28, 7:13 pm, Michele Simionato <michele.simion...@gmail.com>
wrote:

> This morning I did some experiment with a simplified version
> of the code, by putting many libraries in the same file and using
> (import for expand) and it worked, but I cannot get the real code to
> compile now. I cannot work on it this evening, so I will leave it for
> tomorrow.

Update: I was able to make the code to run both with Ikarus and PLT,
by splitting it into three files. For the curious, here it is:
http://www.phyast.pitt.edu/~micheles/scheme/sweet-macros.zip.
Notice: I did not perform any non-trivial tests in PLT, so I am not
really sure it works as it should.

Abdulaziz Ghuloum

unread,
Oct 30, 2008, 2:40:17 AM10/30/08
to
Michele Simionato wrote:

> Update: I was able to make the code to run both with Ikarus
> and PLT, by splitting it into three files.

The single library version was more sweet IMHO. As if writing
syntax-case macros was not hard enough. Pop quiz for all: are
all the specified "for --- run expand" phases in all libraries
needed, or are some superfluous? Justify for exact credit.

Aziz,,,

Michele Simionato

unread,
Oct 30, 2008, 2:49:12 AM10/30/08
to
On Oct 30, 7:40 am, Abdulaziz Ghuloum <aghul...@cee.ess.indiana.edu>
wrote:

I am nearly sure some are superfluous, but I did not want to spend
more time fighting with PLT Scheme phase separation worries. You know,
I have a day job too! ;)

Derick Eddington

unread,
Oct 30, 2008, 7:50:09 AM10/30/08
to
On Oct 28, 3:44 am, Jens Axel Soegaard

No:

[d@eep:~/.plt-scheme/4.1.2.2/collects]-> cat A/main.sls
#!r6rs
(library (A)
(export foo)
(import (rnrs))
(define-syntax foo
(syntax-rules ()
[(_) "A:foo"])))
[d@eep:~/.plt-scheme/4.1.2.2/collects]-> cat B/main.sls
#!r6rs
(library (B)
(export bar)
(import (rnrs) (for (A) expand))
(define-syntax foo
(syntax-rules ()
[(_) "B:foo"]))
(define-syntax bar
(lambda (_)
#`'(B:bar #,(foo)))))
[d@eep:~/.plt-scheme/4.1.2.2/collects]-> cat ~/t10/use-A-B.sps
#!r6rs
(import (rnrs) (B))
(write (bar)) (newline)
[d@eep:~/.plt-scheme/4.1.2.2/collects]-> mzscheme ~/t10/use-A-B.sps
(B:bar "A:foo")
[d@eep:~/.plt-scheme/4.1.2.2/collects]-> ikarus --r6rs-script ~/t10/
use-A-B.sps
Unhandled exception:
Condition components:
1. &who: foo
2. &message: "multiple definitions of identifier"
3. &syntax:
form: foo
subform: #f
4. &source-information:
file-name: "./B/main.sls"
character: 88
5. &trace: #<syntax foo (char 88 of ./B/main.sls)>
[d@eep:~/.plt-scheme/4.1.2.2/collects]->

--
: Derick
----------------------------------------------------------------

leppie

unread,
Oct 30, 2008, 8:43:55 AM10/30/08
to
On Oct 30, 1:50 pm, Derick Eddington <derick.edding...@gmail.com>
wrote:

Or just rename the imported 'foo'. Problem solved :)

Eli Barzilay

unread,
Oct 30, 2008, 9:51:41 AM10/30/08
to
On Oct 30, 2:40 am, Abdulaziz Ghuloum <aghul...@cee.ess.indiana.edu>
wrote:

I'll bite:

The single-library version was more messy/confusing IMHO. As if
writing `syntax-case' macros was not hard enough. Pop quiz: the
question that Jens asked (plus a bunch of other situations where
state is involeved and/or where some bindings are mentioned at
multiple levels). Justify for extra credit.

--
((lambda (x) (x x)) (lambda (x) (x x))) Eli
Barzilay:
http://www.barzilay.org/ Maze is
Life!

Abdulaziz Ghuloum

unread,
Oct 30, 2008, 10:49:42 AM10/30/08
to
Eli Barzilay wrote:
> On Oct 30, 2:40 am, Abdulaziz Ghuloum <aghul...@cee.ess.indiana.edu>
> wrote:
>> Michele Simionato wrote:
>>> Update: I was able to make the code to run both with Ikarus
>>> and PLT, by splitting it into three files.
>> The single library version was more sweet IMHO. As if writing
>> syntax-case macros was not hard enough. Pop quiz for all: are
>> all the specified "for --- run expand" phases in all libraries
>> needed, or are some superfluous? Justify for exact credit.
>
> I'll bite:
>
> The single-library version was more messy/confusing IMHO. As if
> writing `syntax-case' macros was not hard enough. Pop quiz: the
> question that Jens asked (plus a bunch of other situations where
> state is involeved and/or where some bindings are mentioned at
> multiple levels). Justify for extra credit.

Sorry Eli, that was not the correct answer. (It was actually not
an answer at all. You shouldn't answer questions with questions).

Aziz,,,

Abdulaziz Ghuloum

unread,
Oct 30, 2008, 11:48:39 AM10/30/08
to
Derick Eddington wrote:
> On Oct 28, 3:44 am, Jens Axel Soegaard
>> What happens in the following situation:
>>
>> Library A:
>>
>> (define-syntax foo (lambda (stx) ---1))
>>
>> Library B imports A:
>>
>> (define-syntax foo (lambda (stx) ---2))
>>
>> (define-syntax bar (lambda (stx) --- foo ---))
>>
>> Will PLT and Ikarus behave the same here?
>
> No:

Regardless of phasing semantics, R6RS specifies the following:

Quote from R6RS:

An identifier can be imported with the same local name from two or more
libraries or for two levels from the same library only if the binding
exported by each library is the same (i.e., the binding is defined in
one library, and it arrives through the imports only by exporting and
re-exporting). Otherwise, no identifier can be imported multiple times,
defined multiple times, or both defined and imported. No identifiers are
visible within a library except for those explicitly imported into the
library or defined within the library.

End of Quote

So, the you cannot have foo both defined in a library and at the same
time imported into that library. Similarly, you cannot have two
different foos defined in two different libraries imported into the
same place, regardless of phasing.

E.g., if you have:

(library (A) (export x) (import (rnrs)) (define x ---))

and

(library (B) (export x) (import (rnrs)) (define x ---))

then the following is not a valid library definition:

(library (C) (export) (import (for (A) run) (for (B) expand)))

And indeed, it fails under all of Ikarus, Larceny, and Ypsilon
with a clear description of the error.

You need to confirm with Matthew whether this behavior of mzscheme
was intended or just an oversight.

Aziz,,,

Eli Barzilay

unread,
Oct 30, 2008, 2:36:39 PM10/30/08
to
On Oct 30, 10:49 am, Abdulaziz Ghuloum <aghul...@cee.ess.indiana.edu>

wrote:
> Eli Barzilay wrote:
> > On Oct 30, 2:40 am, Abdulaziz Ghuloum <aghul...@cee.ess.indiana.edu>
> > wrote:
> >> The single library version was more sweet IMHO. As if writing
> >> syntax-case macros was not hard enough. Pop quiz for all: are
> >> all the specified "for --- run expand" phases in all libraries
> >> needed, or are some superfluous? Justify for exact credit.
> >
> > I'll bite:
> >
> > The single-library version was more messy/confusing IMHO. As if
> > writing `syntax-case' macros was not hard enough. Pop quiz: the
> > question that Jens asked (plus a bunch of other situations where
> > state is involeved and/or where some bindings are mentioned at
> > multiple levels). Justify for extra credit.
>
> Sorry Eli, that was not the correct answer.

(I leave that to DrScheme's "check syntax" button, which highlights in
red unused requires.)


> (It was actually not an answer at all. You shouldn't answer
> questions with questions).

Q: Why does a Jew answer a question with a qiestion?

A: Why not?

Jens Axel Soegaard

unread,
Oct 30, 2008, 3:25:00 PM10/30/08
to
Abdulaziz Ghuloum wrote:
> Derick Eddington wrote:
>> On Oct 28, 3:44 am, Jens Axel Soegaard
>>> What happens in the following situation:
>>>
>>> Library A:
>>>
>>> (define-syntax foo (lambda (stx) ---1))
>>>
>>> Library B imports A:
>>>
>>> (define-syntax foo (lambda (stx) ---2))
>>>
>>> (define-syntax bar (lambda (stx) --- foo ---))
>>>
>>> Will PLT and Ikarus behave the same here?
>>
>> No:

I was a bit unclear on how B imports A (because I didn't
think the question through).

Let's try a few examples in the "Pretty Big" language.
First let's try Derrick's example, which gave the
provoked the exception "multiple definitions of identifier"
in Ikarus.

(module a scheme
(provide foo)


(define-syntax foo (syntax-rules () [(_) "A:foo"])))

(module b scheme
(require-for-syntax 'a)
(provide foo bar)
(define-syntax foo "b:foo")
(define-syntax bar (lambda (_) #`'(b:bar #,(foo)))))

(require 'b)
(bar)

expand: unbound identifier in module (in the transformer


environment, which does not include the macro definition

that is visible to run-time expressions) in: foo
(the use of foo i.e. (foo) is colored red)


Now let's try importing A in a different phase:

(module a scheme
(provide foo)


(define-syntax foo (syntax-rules () [(_) "A:foo"])))

(module b scheme
(require 'a)
(provide foo bar)
(define-syntax foo "b:foo")
(define-syntax bar (lambda (_) #`'(b:bar #,(foo)))))

(require 'b)
(bar)

This gives the error:

module: identifier is already imported in: foo
(the foo in module B is colored red)

Finally let's import A with (for-meta 1 a)

(module a scheme
(provide foo)


(define-syntax foo (syntax-rules () [(_) "A:foo"])))

(module b scheme
(require (for-meta 1 'a))
(provide foo bar)
(define-syntax foo "b:foo")
(define-syntax bar (lambda (_) #`'(b:bar #,(foo)))))

(require 'b)
(bar)

This runs and gives:

(b:bar "A:foo")


What I was hoping was to find a situation similar to:

> MzScheme does not like it if you do:
> (define-syntax foo (lambda (stx) ---))

> (define-syntax bar (lambda (stx) --- foo ---))

> while Ikarus allows it. Ikarus says: hey, we have the transformer,
> so, we might as well make it available. MzScheme says: hey, if you
> can't access run-time variables, then you can't access run-time
> macros either.

Since the first example gave this error,

expand: unbound identifier in module (in the transformer


environment, which does not include the macro definition

that is visible to run-time expressions) in: foo
(the use of foo i.e. (foo) is colored red)

I think the conclusion is that MzScheme detects the situation,
and thus Matthew deliberately chose this behaviour. But why?

I think it was an oversigt, due to the error messages in the
first two examples above.

--
Jens Axel Søgaard

Abdulaziz Ghuloum

unread,
Oct 30, 2008, 3:30:46 PM10/30/08
to
Eli Barzilay wrote:

> Q: Why does a Jew answer a question with a qiestion?
>
> A: Why not?

Sorry, not allowed to laugh.

Jens Axel Soegaard

unread,
Oct 30, 2008, 3:43:27 PM10/30/08
to
Jens Axel Soegaard wrote:
> Abdulaziz Ghuloum wrote:

>> You need to confirm with Matthew whether this behavior of mzscheme
>> was intended or just an oversight.
>
> I think it was an oversigt, due to the error messages in the
> first two examples above.

Fixed in SVN.

--
Jens Axel Søgaard

Derick Eddington

unread,
Oct 31, 2008, 12:21:11 AM10/31/08
to
On Oct 30, 4:50 am, Derick Eddington <derick.edding...@gmail.com>
wrote:

> [d@eep:~/.plt-scheme/4.1.2.2/collects]-> cat A/main.sls
> [...]

> [d@eep:~/.plt-scheme/4.1.2.2/collects]-> cat B/main.sls
> [...]

> [d@eep:~/.plt-scheme/4.1.2.2/collects]-> cat ~/t10/use-A-B.sps
> [...]

> [d@eep:~/.plt-scheme/4.1.2.2/collects]-> ikarus --r6rs-script ~/t10/use-A-B.sps

JTMI, this example showed ikarus resolving a library (A) to the file ./
A/main.sls , but this is experimental and might change.

--
: Derick
----------------------------------------------------------------

namekuseijin

unread,
Oct 31, 2008, 12:57:01 AM10/31/08
to
On 30 out, 17:30, Abdulaziz Ghuloum <aghul...@cee.ess.indiana.edu>
wrote:

Too bad. It's not racist joke and genuinely fun in a puerile
way... :)

Abdulaziz Ghuloum

unread,
Oct 31, 2008, 4:45:14 PM10/31/08
to

Thanks Jens for the update. I hope this suffices as an answer to Eli.

Aziz,,,

Eli Barzilay

unread,
Oct 31, 2008, 10:58:45 PM10/31/08
to
On Oct 31, 4:45 pm, Abdulaziz Ghuloum <aghul...@cee.ess.indiana.edu>
wrote:

>
> Thanks Jens for the update.  I hope this suffices as an answer to Eli.

(Of course not, I didn't ask any real question...)

Abdulaziz Ghuloum

unread,
Oct 31, 2008, 11:17:33 PM10/31/08
to
Eli Barzilay wrote:
> On Oct 31, 4:45 pm, Abdulaziz Ghuloum <aghul...@cee.ess.indiana.edu>
> wrote:
>> Thanks Jens for the update. I hope this suffices as an answer to Eli.
>
> (Of course not, I didn't ask any real question...)

Sorry. It was only an incomplete sentence fragment that I incorrectly
mistook for a question in the form of a pop quiz. My bad.

Aziz,,,

Eli Barzilay

unread,
Nov 1, 2008, 9:34:01 AM11/1/08
to
On Oct 31, 11:17 pm, Abdulaziz Ghuloum <aghul...@cee.ess.indiana.edu>

wrote:
> Eli Barzilay wrote:
> > On Oct 31, 4:45 pm, Abdulaziz Ghuloum <aghul...@cee.ess.indiana.edu>
> > wrote:
> >> Thanks Jens for the update. I hope this suffices as an answer to Eli.
>
> > (Of course not, I didn't ask any real question...)
>
> Sorry. It was only an incomplete sentence fragment that I
> incorrectly mistook for a question in the form of a pop quiz. My
> bad.

(*sigh* My guess is that you know all that, but since you keep
pulling my tongue...)

If you really need it spelled out: I think that the lack of phase
separation, or rather the intentional phase-mis-separation is not a
good idea. What you semi-jokingly described with "hey, we have the
transformer, so, we might as well make it available" is -- IMO -- a
mistake much like Perl's "hey, we know how to print the number we
might as well make it usable as a string". However, I think that in
the phase case the error is more severe: I see the two phases as
completely separate worlds, with completely separate semantics, and
the fact that some of the names coincide should not make that any
different. (And it's more than just seeing it: I'm actually using
this feature.)

You also said "As if writing syntax-case macros was not hard enough"
-- which is a good point: writing algorithms is a tough job, adding
weird puns like making numbers behave like string helps write shorter
code -- but it certainly does not help write code. It's basically the
language trying to second guess what you're trying to say, in a way
that is "mostly obvious enough" that you won't get any nasty surprises
-- and when done at the level of bindings, it can be much more
dangerous. In other words, the lack of "hey, we have a binding" kind
of guesses, and the explicit in-code mention of which bindings go in
which phase are exactly features that *help* write `syntax-case'
macros.

After all, the body of a `define-syntax' *is* in a different world
whether you like it or not (or else you must forbid separate
compilation), and if it's in a different world, pretending that it
isn't by guessing which binding goes where can make the code a little
shorter, but at the expense of hopelessly confusing some people. This
thread started from a confusion over it, from someone who seems
experienced enough to quickly get what's going on; how hard would a
`define-syntax' newbie crash? Any kind of beginner course that I have
seen (which is much more than htdp-style courses) is making things
explicit for newbies, because it helps to master things explicitly
before you can deal with a "usually-fine" implicit guess.

-- So, "as if writing syntax-case macros was not hard
enough"... exactly! -- Why complicate their lives with implicit
guessing?

As for R6RS modules being forbidden from having the same name exist at
two levels if it doesn't come from the same source... Well... As
someone once said "R6RS is \"perfect\".".

Abdulaziz Ghuloum

unread,
Nov 1, 2008, 6:18:03 PM11/1/08
to
Eli Barzilay wrote:
> On Oct 31, 11:17 pm, Abdulaziz Ghuloum <aghul...@cee.ess.indiana.edu>
> wrote:
>> Eli Barzilay wrote:
>>> On Oct 31, 4:45 pm, Abdulaziz Ghuloum <aghul...@cee.ess.indiana.edu>
>>> wrote:
>>>> Thanks Jens for the update. I hope this suffices as an answer to Eli.
>>> (Of course not, I didn't ask any real question...)
>> Sorry. It was only an incomplete sentence fragment that I
>> incorrectly mistook for a question in the form of a pop quiz. My
>> bad.
>
> (*sigh* My guess is that you know all that, but since you keep
> pulling my tongue...)

I wouldn't be able to pull your tongue had it not extended this far.
Your tongue aside ...

> If you really need it spelled out: I think that the lack of phase
> separation, or rather the intentional phase-mis-separation is not a
> good idea. What you semi-jokingly described with "hey, we have the
> transformer, so, we might as well make it available" is -- IMO -- a
> mistake much like Perl's "hey, we know how to print the number we
> might as well make it usable as a string".

First off, your argument goes like "X is like Y (pulling inapplicable
analogy out of the blue), but Y is bad, so X must be bad". This is
like saying "phish (the band) sounds a lot like fish, but fish stinks
so I won't go to the concert". So, Perl aside, ...

> However, I think that in
> the phase case the error is more severe: I see the two phases as
> completely separate worlds, with completely separate semantics, and
> the fact that some of the names coincide should not make that any
> different.

Well, we are not entitled to your view of the world. In my view
(which you're not obliged to follow), an imported identifier (say
lambda, cond, foo, or whatever), means exactly the same thing at
all times. Is this more confusing than your view?

> (And it's more than just seeing it: I'm actually using this feature.)

I hope this is not implying that my "feature" is useless, because
I use my feature too, you know.


> You also said "As if writing syntax-case macros was not hard enough"
> -- which is a good point: writing algorithms is a tough job, adding
> weird puns like making numbers behave like string helps write shorter
> code -- but it certainly does not help write code. It's basically the
> language trying to second guess what you're trying to say, in a way
> that is "mostly obvious enough" that you won't get any nasty surprises
> -- and when done at the level of bindings, it can be much more
> dangerous.

Your Perl analogies aside again ...

Who is "second guessing" what? And what's this nasty surprising
danger that you speak of? Are you talking about nuclear missiles
flying out of my expand-time environment? (because that would be
funny)

Sounds like you're trying to spread fear, uncertainty, and doubt
about my system.


> In other words, the lack of "hey, we have a binding" kind
> of guesses, and the explicit in-code mention of which bindings go in
> which phase are exactly features that *help* write `syntax-case'
> macros.

Crap. Sorry. It doesn't for me. Or else I would've done something
similar in Ikarus. As a matter of fact, the whole point of Ikarus's
implementation of libraries is to eliminate such "help"; thank you
very much.


> After all, the body of a `define-syntax' *is* in a different world
> whether you like it or not

NO! Stop here!

Syntax definitions are expanded and evaluated in left-to-right order
in which they appear in an definition context. That means, that at
*expand time*, at the point [*] of the library below, the right-hand-
side expression of the foo syntax definition is already expanded,
evaluated, and *is* in the expand-time environment.

(library (acme)
(export ---)
(import ---)
(define-syntax foo ---)
; [*]
(define-syntax bar --- (foo) ---))

The reference to foo in (foo) at the right-hand-side expression of
bar is *also* done at expand time, the time in which the definition
of the foo macro clearly exists, expanded, evaluated, and ready to
be applied.


> (or else you must forbid separate compilation),

Clearly I must not forbid separate compilation since Ikarus provides
both this *and* separate compilation. Do you really think that
MzScheme's model is the only way to achieve separate compilation?
That would be a good joke.


> and if it's in a different world, pretending that it
> isn't by guessing which binding goes where can make the code a little
> shorter, but at the expense of hopelessly confusing some people.

The "think of the poor confused children" argument does not fly Eli.

> This thread started from a confusion over it, from someone who seems
> experienced enough to quickly get what's going on; how hard would a
> `define-syntax' newbie crash?

The only thing I saw Michele confused about was when he tried to use
mzscheme to be surprised that it did not allow him to do things that
were clearly meaningful without going through hoops (the last of which
would've lost him his day job).


> Any kind of beginner course that I have
> seen (which is much more than htdp-style courses) is making things
> explicit for newbies, because it helps to master things explicitly
> before you can deal with a "usually-fine" implicit guess.

Are you still making the "think of the poor noob" argument?


> -- So, "as if writing syntax-case macros was not hard
> enough"... exactly! -- Why complicate their lives with implicit
> guessing?

Stop saying "guessing". Nobody is guessing anything.


> As for R6RS modules being forbidden from having the same name exist at
> two levels if it doesn't come from the same source...

As a matter of fact, this point has never even been controversial
during the R6RS discussion period. If you thought that was not the
right behavior, why didn't you speak up? Or why didn't anyone else
think that it's better to be able to import different bindings with
different semantics but with the same name into different phases?


> Well... As someone once said "R6RS is \"perfect\".".

Wow. Didn't we go a long way just to go back to the "R6RS sucks"
argument.

Aziz,,,

Derick Eddington

unread,
Nov 2, 2008, 2:05:40 AM11/2/08
to
The paper "Implicit Phasing for R6RS Libraries" by Abdulaziz Ghuloum
and R. Kent Dybvig [1] describes the rationale and advantages of their
implicit phasing design.

It makes a case for why libraries should be expanded only once in
order "to avoid inconsistencies that may appear in the set of
identifiers exported by a library" which may result in unlinkable
programs.

It describes advantages of how a single-expansion guarantee can be
used productively.

It says: "the set of programs whose phases can be inferred is larger
than the set that can be explicitly specified. This is due to the fact
that the set of phases that the library can specify is fixed".

It also says: "Another reason why we chose to have no more than one
instance of a library is that system programming requires the ability
to manage resources, some of which cannot be replicated."

It also says: "It would be straightforward, however, to modify our
implementation to maintain separate environments for each phase and to
evaluate transformer and variable bindings once per phase. In
particular, the implicit phasing model does not inhibit doing so in
any way."

The R6RS says the (rnrs) library implicitly exports its bindings for
run and expand phases for convenience. However, importing (rnrs) for
other levels can still be necessary. The existence of negative levels
complicates things further. With the explicit phasing design, the
user has to figure out what these levels need to be, and for negative
levels this sounds even more confusing than for positive levels. The
implicit phasing design puts the burden of figuring out the necessary
phases on the implementation and not on the user.

There's also formal comments #92 and #123 which are about the implicit
versus explicit design [2][3]

[1] http://portal.acm.org/citation.cfm?id=1291151.1291197
[2] http://www.r6rs.org/formal-comments/comment-92.txt
[3] http://www.r6rs.org/formal-comments/comment-123.txt

--
: Derick
----------------------------------------------------------------

Michele Simionato

unread,
Nov 2, 2008, 2:44:04 AM11/2/08
to
On Nov 2, 8:05 am, Derick Eddington <derick.edding...@gmail.com>
wrote:
> [1]http://portal.acm.org/citation.cfm?id=1291151.1291197

There is something I have always wanted to ask about Computer Science
papers. It seems that if I want to read the paper I must subscribe to
the site and to buy it. That looks strange to me, since I am used to
the publication system we use in Physics.
You must pay for peer-reviewed papers appeared in formal publications
(actually it is the University which pays the
subscription) however in practice nobody reads the published
versions, because he has already read the preprint.
Virtually all papers appears as preprint, freely downloadable
from the xxx archives (for instance from http://xxx.lanl.gov/form/hep-th
for Theoretical Physics). Preprints appear months before the official
publication, so people wanting to stay updated look at the preprints,
not at the formal publications. The formal publications are still
important, but only because they have much more value in your CV than
a preprint.
Is there something like that for Computer Science publications?
How commonly used is it?

Michele Simionato

Eli Barzilay

unread,
Nov 2, 2008, 3:07:11 AM11/2/08
to
On Nov 2, 2:05 am, Derick Eddington <derick.edding...@gmail.com>
wrote:
> [...]

Right -- note that the response to the first says:

| The current specification reflects a compromise among different
| possible models of libraries and syntax.

and the the response to the second:

| R6RS will maintain a compromise position that allows both explicit,
| enfored levels and implicit phasing (i.e., where `for' is
| effectively ignored).

In other words, the R6RS restriction on identifiers at different
levels is a compromise that helped avoid a controversy.

Eli Barzilay

unread,
Nov 2, 2008, 3:18:26 AM11/2/08
to
On Nov 1, 5:18 pm, Abdulaziz Ghuloum <aghul...@cee.ess.indiana.edu>

wrote:
> Eli Barzilay wrote:
>
> > If you really need it spelled out: I think that the lack of phase
> > separation, or rather the intentional phase-mis-separation is not
> > a good idea. What you semi-jokingly described with "hey, we have
> > the transformer, so, we might as well make it available" is -- IMO
> > -- a mistake much like Perl's "hey, we know how to print the
> > number we might as well make it usable as a string".
>
> First off, your argument goes like "X is like Y (pulling inapplicable
> analogy out of the blue), but Y is bad, so X must be bad". This is
> like saying "phish (the band) sounds a lot like fish, but fish stinks
> so I won't go to the concert". So, Perl aside, ...

No, in fact the analogy is very relevant. Here's a more explicit
rephrase -- when I write:

> (define count!
(let ([c 0])
(lambda () (set! c (add1 c)) c)))
> (define-syntax foo
(lambda (stx)
(syntax-case stx ()
[(_ name) (with-syntax ([c (count!)])
#'(define (name) (list c (count!))))])))

I expect an error which is very much like a type error (where in this
case, the error is actually an unbound identifier). Therefore, the
result that Ikarus produces:

> (foo x)
> (x)
(1 2)

looks to me (note: to *me*) like a confusing result of the lack of
error. It looks to me like the same kind of "we'll do the right thing
instead of throwing an error" which results in 1+2=12 which you can
run into in languages that are heavy on the puns. Masking out these
kinds of errors is -- IMO -- an attempt to make the language *guess*
what you mean: "hey, we know how a number prints, we can just as well
append it as a string", and "hey, we have a binding at a different
level, we might as well use it".


> > However, I think that in the phase case the error is more severe:

Further explanation: it is more severe IMO because an "unbound
identifier" indicates a more important flaw in your code than "an
integer instead of a string".


> [...trivialities snipped...]

(See the last paragraph.)

> > You also said "As if writing syntax-case macros was not hard enough"
> > -- which is a good point: writing algorithms is a tough job,
> > adding weird puns like making numbers behave like string helps
> > write shorter code -- but it certainly does not help write code.
> > It's basically the language trying to second guess what you're
> > trying to say, in a way that is "mostly obvious enough" that you
> > won't get any nasty surprises -- and when done at the level of
> > bindings, it can be much more dangerous.
>
> Your Perl analogies aside again ...
>
> Who is "second guessing" what? And what's this nasty surprising
> danger that you speak of? Are you talking about nuclear missiles
> flying out of my expand-time environment? (because that would be
> funny)

I hope that the above clarifies these questions. Translating that to
an an amusing example involving erroneous call to
`send-nuclear-missiles' from a macro is left as an exercise.


> Sounds like you're trying to spread fear, uncertainty, and doubt
> about my system.

How did you get to *that* conclusion? Obviously, there's a design
decision to do here, and obviously there are reasons for both sides
expressed as two implementations. You started this whole thing with
pointing out these two sides:

| karus says: hey, we have the transformer, so, we might as well make


| it available. MzScheme says: hey, if you can't access run-time
| variables, then you can't access run-time macros either.

but later you chose to point to the Ikarus approach as better:

| As if writing syntax-case macros was not hard enough.

All I wanted to do was reiterate the fact that this coin has a flip
side too. I explicitly tried to avoid a "my scheme can piss farther
away than your scheme" contest, but you refused[*] to let it go at
that.

([*] By writing "I hope this suffices as an answer to Eli" when you're
aware of me not having any question in the first place. If you really
missed the fact that my "question" was a tongue-in-cheek paraphrase of
your own question then I apologize for assuming you did.)

The rest of your post is littered with snide remarks that will easily
lead to redundant flaming. (Some also appear above, and realizing
this, I chose to remove it together with the reply I wrote in an
attempt to stop the rolling ball of flames.) If you really want to
discuss this issue, then please focus on the technical aspects.
Personally, I have no interest in doing so, so the ball is in your
hands.

Michele Simionato

unread,
Nov 2, 2008, 4:44:01 AM11/2/08
to
On Nov 2, 9:18 am, Eli Barzilay <e...@barzilay.org> wrote:
> when I write:
>
>   > (define count!
>       (let ([c 0])
>         (lambda () (set! c (add1 c)) c)))
>   > (define-syntax foo
>       (lambda (stx)
>         (syntax-case stx ()
>           [(_ name) (with-syntax ([c (count!)])
>                       #'(define (name) (list c (count!))))])))
>
> I expect an error which is very much like a type error (where in this
> case, the error is actually an unbound identifier).  Therefore, the
> result that Ikarus produces:
>
>   > (foo x)
>   > (x)
>   (1 2)
>
> looks to me (note: to *me*) like a confusing result of the lack of
> error.

But why do you expect an unbound identifier error? Which identifier?
To me Ikarus is doing exactly what I would expect.
I am not interested in flames, I recognize that both you and Aziz are
much more knowledgeable than me. I can just report anedoctical
impressions from an user point of you. Still, sometimes it makes sense
to hear what users say.

I started programming in Scheme with PLT, but after a couple of months
I switched to Chicken, for various reasons. One of the reasons is that
I hated the phase separation thing. To me, it looked absurd that I had
to put helper functions for a macro in a different module, when they
were logically strictly connected to the macro and only to that macro.
For a while I thought Chicken did not have this phase separation and I
was happy with that. Then, I started compiled my scripts and
discovered that the phase separation was there, visible in compiled
code but not in interpreted code. So I was unhappy and I bugged Felix
for a while until I understood eval-when (this was nearly four years
ago). I sorta of understood that phase separation was needed in order
to ensure separate compilation so I decided it was a thing I had to
live with. Then, Ikarus came out, with
separate compilation and without phase separation. I still do not
understand how it works its magic, but it is a proof that the
semantics I have always wanted as an user is technically possible. At
this point I do not understand if phase separation is just a technical
convenience for compilation strategies such as Scheme->C translation
or if, as you imply, it is needed to avoid subtle bugs. If so, I would
like to see a better example than the one you give, since to me the
code is doing the right thing (there is a single binding for c, both a
compile time and runtime).

P.S. Eli's example written with my own sweet-macros library, just to
see how it looks:

(import (rnrs) (sweet-macros))

(define incr!


(let ([c 0])
(lambda () (set! c (add1 c)) c)))

(def-syntax (define-counter name)
#`(define (name) (list #,(incr!) (incr!))))

(define-counter c)
(c) ;=> (1 2)

leppie

unread,
Nov 2, 2008, 5:45:30 AM11/2/08
to
On Nov 2, 10:18 am, Eli Barzilay <e...@barzilay.org> wrote:
> No, in fact the analogy is very relevant.  Here's a more explicit
> rephrase -- when I write:
>
>   > (define count!
>       (let ([c 0])
>         (lambda () (set! c (add1 c)) c)))
>   > (define-syntax foo
>       (lambda (stx)
>         (syntax-case stx ()
>           [(_ name) (with-syntax ([c (count!)])
>                       #'(define (name) (list c (count!))))])))
>
> I expect an error which is very much like a type error (where in this
> case, the error is actually an unbound identifier).  Therefore, the
> result that Ikarus produces:
>
>   > (foo x)
>   > (x)
>   (1 2)
>
> looks to me (note: to *me*) like a confusing result of the lack of
> error.  

The lack of the expected error is due to REPL.

Using the same two expressions in a top level program or library
results in:

$ ikarus --r6rs-script test.ss
Unhandled exception:
Condition components:
1. &who: count!
2. &message: "identifier out of context"
3. &syntax:
form: count!
subform: #f
4. &source-information:
file-name: "test.ss"
character: 187
5. &trace: #<syntax count! (char 187 of test.ss)>

Cheers

leppie

Michele Simionato

unread,
Nov 2, 2008, 6:31:29 AM11/2/08
to
On Nov 2, 11:45 am, leppie <xacc....@gmail.com> wrote:
> The lack of the expected error is due to REPL.
>
> Using the same two expressions in a top level program or library
> results in:
>
> $ ikarus --r6rs-script test.ss
> Unhandled exception:
>  Condition components:
>    1. &who: count!
>    2. &message: "identifier out of context"
>    3. &syntax:
>        form: count!
>        subform: #f
>    4. &source-information:
>        file-name: "test.ss"
>        character: 187
>    5. &trace: #<syntax count! (char 187 of test.ss)>

Indeed. Notice that in my answer to Eli I made a mistake talking about
helper functions when I should have said "helper macros".
The fact that helper functions have to be defined in a separate module
for compiled code did not confuse me, when writing sweet-macros. My
confusion arose from helper macros. This code contains an helper macro
"sub" and makes the issue clear:

(import (rnrs))

(define-syntax sub
(syntax-rules ()
((_ pattern template) (syntax-rules () (pattern template)))))

(define-syntax double
(sub (_ x) '(x x)))

(display (double x))

It works as I expect in Ikarus, both in compiled and interpreted code.
It does not work in PLT and I do not yet understand why. In my view
(please correct me if I am wrong) first of all the compiler look at
syntax definitions, then it expands the syntax forms and then it looks
at the resulting code for definitions. Clearly if the syntax form
needs an helper function to be defined, such a function has to be
available first, and that can be done by importing it from another
module and making it available at compile time. However in this case I
have a helper macro "sub", which is definite *at compile time* before
its use in double *at compile time*, so I expected that helper macro
to be recognized without putting it in an external module.

Abdulaziz Ghuloum

unread,
Nov 2, 2008, 11:03:18 AM11/2/08
to
leppie wrote:

> The lack of the expected error is due to REPL.
>
> Using the same two expressions in a top level program or library

> results in: ...

That's correct. In Ikarus's repl, once a top-level variable is defined,
it is accessible from anywhere within the repl. But we were discussing
library semantics, so, the repl example from Eli was a red herring.

Aziz,,,

Abdulaziz Ghuloum

unread,
Nov 2, 2008, 11:19:08 AM11/2/08
to
Michele Simionato wrote:

> Indeed. Notice that in my answer to Eli I made a mistake talking about
> helper functions when I should have said "helper macros".
> The fact that helper functions have to be defined in a separate module
> for compiled code did not confuse me, when writing sweet-macros.

Correct.

> My confusion arose from helper macros. This code contains an helper
> macro "sub" and makes the issue clear:
>
> (import (rnrs))
>
> (define-syntax sub
> (syntax-rules ()
> ((_ pattern template) (syntax-rules () (pattern template)))))
>
> (define-syntax double
> (sub (_ x) '(x x)))
>
> (display (double x))
>
> It works as I expect in Ikarus, both in compiled and interpreted code.
> It does not work in PLT and I do not yet understand why.

That's the question.

> In my view
> (please correct me if I am wrong) first of all the compiler look at
> syntax definitions, then it expands the syntax forms and then it looks
> at the resulting code for definitions.

It's a little more interleaved than that. In definitions context
(e.g., top-level program, library top-level, internal definitions),
it processes the body forms one by one looking for definitions. If
it encounters a define-syntax, the right-hand-side is expanded and
evaluated and made available for expanding subsequent forms from
that point on. If it encounters a macro use, it expands the macro,
splices it in place of the input form and resumes with the resulting
body forms. If it encounters a variable definition, it does NOT
expand the right-hand-side expression, instead, it queues it until
all definitions (variables and macros) are found. At that point,
the body expressions and right-hand-side expressions of variable
definitions (that were queued) are expanded.

At any rate, macro definitions *are* expanded and evaluated to
obtain the transformer procedure *before* expansion of the rest of
the definitions resumes. This is true for all R6RS implementations
regardless of what they think of cross-library phasing, or whether
macros are defined for single level or for all levels.


> Clearly if the syntax form
> needs an helper function to be defined, such a function has to be
> available first, and that can be done by importing it from another
> module and making it available at compile time.

Correct too. And in Ikarus, you don't need to do anything special
to make that happen.

> However in this case I
> have a helper macro "sub", which is definite *at compile time* before
> its use in double *at compile time*, so I expected that helper macro
> to be recognized without putting it in an external module.

The answer I gave to this was:

"Ikarus says: hey, we have the transformer, so, we might as well make


it available. MzScheme says: hey, if you can't access run-time
variables, then you can't access run-time macros either."

but this stirred some emotions, so, I guess it was not the right
answer, or might have not been phrased correctly, or whatever. I too
would like to know the right answer to your question.

Aziz,,,

Eli Barzilay

unread,
Nov 2, 2008, 1:56:22 PM11/2/08
to
On Nov 2, 6:31 am, Michele Simionato <michele.simion...@gmail.com>
wrote:

> On Nov 2, 11:45 am, leppie <xacc....@gmail.com> wrote:
>
> > The lack of the expected error is due to REPL.
>
> > Using the same two expressions in a top level program or library
> > results in:
>
> > $ ikarus --r6rs-script test.ss
> > Unhandled exception:
> > Condition components:
> > 1. &who: count!
> > 2. &message: "identifier out of context"
> > 3. &syntax:
> > form: count!
> > subform: #f
> > 4. &source-information:
> > file-name: "test.ss"
> > character: 187
> > 5. &trace: #<syntax count! (char 187 of test.ss)>
>
> Indeed.

[I should have been clearer about my example, but due to other reasons
preferred to avoid making my reply longer.]

I know that you get that error if you're not on the REPL -- but at a
minimum, I would expect the *same* error at the REPL. (Translation:
if I were using Ikarus, I would report the lack of error on the REPL
as a bug.) IMO, that would make the implicit phasing more consistent
and therefore more reasonable. Using the implicit number to string
coercion analogy: the fact that Perl/whatever is doing so can lead to
surprising bugs, but a good number of such bugs can be avoided if such
implicit coercion marks the binding (I should really talk about a
value) as a string. This means that `a=b+1' can still result in
appending "1" to `b', but if this happens then `b' will be treated
consistently as a string.


> Notice that in my answer to Eli I made a mistake talking about
> helper functions when I should have said "helper macros".

Your mistake is strongly related to the confusion I'm talking about.
A macro is different from a function in that it lives in a separate
world. In a language like C, macros are very obviously coming from a
different world because it's written in a different language. In a
lot of Scheme code, the language used for your macros is written the
same language, but it's still not the same world because of the way
they're evaluated: macros are called at compilation (aka expansion)
time sequentially, and other functions are called at runtime; when you
compile code the latter is never called, and when you run the result
the former is never called.

[In what follows I ignore multiple instantiations of modules. In PLT
this is a feature that allows me to use state in a reliable way in
macros, and I was told that the assumption in Ikarus is that
well-behaved macros should never use state. But to be able to talk
about this I'll need to know better what Ikarus does, and I'm too lazy
to be spending more weekend time...]

Now, Ikarus will guess (IIUC!) whether a particular piece of code goes
in the former or in the latter. By "guess" what I mean is that it
does so without an explicit indication in the user's code -- it does
that implicitly based on uses in the library. This relies on the
macro code being in the same language as runtime code -- and this
leads to the core of the difference. You (as an implementation
designer) might decide in advance that

The language used for writing macros is always the same language as
the one used for runtime code. [Possibly differs in the set of
bindings available, but any binding must have the same meaning,
which is the R6RS restriction.]

But in PLT (or more accurately, in macro systems that do (explicit)
phase separation), there is no need for the two languages to be the
same -- each one can draw its semantics from a different module. So
the question should be -- is this really a useful feature? Well, at
least in the PLT world it's very useful. The PLT code does have
several very different languages; among others there's a typed scheme
language, a lazy one, a reactive one, and even some
"superficially-different" ones like Swindle. There's good questions
there of what is the meaning of having your syntax-level code written
in some X language where X is not the "default" one -- does it make
sense to write macros in typed scheme? In lazy scheme? (That's a
confusing one.) There's other implications of conflating these
levels: PLT's two main executables are MzScheme and MrEd -- the latter
is a GUI extension of the former and requires a windowing system to
run in. So, conceptually speaking, should compiling gui code require
a windowing system too? (BTW, this is where the R6RS restriction can
help, together with something like a policy of not invoking modules
unless their bindings are used, but I won't get into that.)

I'm not writing all of these questions to highlight the PLT solution
as the obvious one or the Ikarus solution as a flawed one -- if you
begin with the assumption that macros are always in the same language,
then you will get a different set of answers than I do.

Sidenote: Back around 10 years ago I was playing with preprocessors,
roughly speaking, I'd write text and <<...>> would mark places with
Scheme that generates replacement text. In this case, the "macro"
language (scheme) is very different than the runtime language (text),
and a natural extension was to apply the same for Scheme code (giving
you text-level CPP-like macros that are written in Scheme), and soon
followed other games like using a different process for the meta-level
marks, possibly with a different language, having different langauges
specified at the meta-level and different processes used for
meta-meta-levels. Eventually, I was able to run text that looks like:

this is plain text
<<scheme code that generates text
<<scheme code that generates scheme code to generate text>>
more scheme code>>
<<TCL: tcl code to generate text, invoking a subprocess>>
<<scheme code <<TCL: tcl code to generate scheme code, running in
a separate subprocess>>>>

How is this related? It explains why *I* would not want the two
phases to be forced to use the same semantics. You're now free to
conclude that I'm clearly an insane freak and ignore any opinions I
express.


> The fact that helper functions have to be defined in a separate
> module for compiled code did not confuse me, when writing
> sweet-macros. My confusion arose from helper macros. This code
> contains an helper macro "sub" and makes the issue clear:
>
> (import (rnrs))
>
> (define-syntax sub
> (syntax-rules ()
> ((_ pattern template) (syntax-rules () (pattern template)))))
>
> (define-syntax double
> (sub (_ x) '(x x)))
>
> (display (double x))
>
> It works as I expect in Ikarus, both in compiled and interpreted
> code. It does not work in PLT and I do not yet understand why.

The right-hand-side of a `define-syntax' is at the syntax phase, and
syntax-phase functions are available to it. But if you want to write
a macro (double, in your case) that uses a macro (sub) in its body
(not in its result), then you're getting to the second (meta-meta)
level up. Here's an example that demonstrates conflating the meta and
meta-meta levels in Ikarus:

(define-syntax m1


(let ([c 0])

(lambda (stx)
(set! c (+ c 1))
(syntax-case stx ()
[(_) (with-syntax ([c c]) #'c)]))))
(define-syntax m2


(lambda (stx)
(syntax-case stx ()

[(_) (let ([c (m1)])
(with-syntax ([c c]) #'c))])))
(display (m1))
(display (m2))


> In my view (please correct me if I am wrong) first of all the
> compiler look at syntax definitions, then it expands the syntax
> forms and then it looks at the resulting code for
> definitions. Clearly if the syntax form needs an helper function to
> be defined, such a function has to be available first, and that can
> be done by importing it from another module and making it available
> at compile time. However in this case I have a helper macro "sub",
> which is definite *at compile time* before its use in double *at
> compile time*, so I expected that helper macro to be recognized
> without putting it in an external module.

Following PLT's phase separation, `sub' is a macro whose body is
written at the meta-meta level, so it doesn't necessarily use the same
semantics that `double' will use. In other words, `double' transforms
runtime code, and `sub' transforms macro code.

leppie

unread,
Nov 2, 2008, 2:50:07 PM11/2/08
to
On Nov 2, 8:56 pm, Eli Barzilay <e...@barzilay.org> wrote:
> [I should have been clearer about my example, but due to other reasons
> preferred to avoid making my reply longer.]
>
> I know that you get that error if you're not on the REPL -- but at a
> minimum, I would expect the *same* error at the REPL.  (Translation:
> if I were using Ikarus, I would report the lack of error on the REPL
> as a bug.)  

The 'error' will occur on the REPL as long as it is a single
expression. Hence the following results in error on REPL:

(let ()
(define count!


(let ([c 0])

(lambda () (set! c (add1 c)) c)))
(define-syntax foo

(lambda (stx)
(syntax-case stx ()

[(_ name) (with-syntax ([c (count!)])

#'(define (name) (list c (count!))))]))) )

Entering the 2 expressions separately is as good as separate
compilation, and thus no error.

Cheers

leppie


andreu...@yahoo.com

unread,
Nov 2, 2008, 3:19:21 PM11/2/08
to

Well, the explicit phase model of PLT (and Larceny) were
invented precisely to prevent this kind of confusion. It is
generally a bad idea, when avoidable, for the same code to
behave differently when compiled than it would in a REPL.
Matthew Flatt wrote a good paper on this issue years ago.

The Dybvig-Ghuloum implicit phasing model has been argued to
be in some aspects more convenient. But it is also in some
ways less expressive. For example, in the Dybvig-Ghuloum
model it is impossible to define an r5rs-like library that
allows only SYNTAX-RULES to be used on the right hand side
of DEFINE-SYNTAX.

As the OP pointed out, users should be aware that superficially
R6RS libraries written for Ikarus do not necessarily port to
PLT/Larceny without modification. OTOH, superficially R6RS
PLT/Larceny libraries are more likely to port to Ikarus
without modification.

Andre

Abdulaziz Ghuloum

unread,
Nov 2, 2008, 3:49:13 PM11/2/08
to
andreu...@yahoo.com wrote:

> The Dybvig-Ghuloum implicit phasing model has been argued to
> be in some aspects more convenient. But it is also in some
> ways less expressive. For example, in the Dybvig-Ghuloum
> model it is impossible to define an r5rs-like library that
> allows only SYNTAX-RULES to be used on the right hand side
> of DEFINE-SYNTAX.

"Impossible" is not the right word. This is trivial:

(library (r5rs-like)
(export define define-syntax syntax-rules quote lambda cons
cond + - ...)
(import (rename (rnrs) [define-syntax defstx]))

(defstx define-syntax
(syntax-rules (syntax-rules)
[(_ name (syntax-rules . rest))
(defstx name (syntax-rules . rest))])))


$ ikarus
> (import (r5rs-like))
> (define-syntax foo (lambda (x) 12))
Unhandled exception
Condition components:
1. &message: "invalid syntax"
2. &syntax:
form: (define-syntax foo (lambda (x) 12))
subform: #f
3. &trace: #<syntax (define-syntax foo (lambda (x) 12))>


Is this cheating?

Aziz,,,

Abdulaziz Ghuloum

unread,
Nov 2, 2008, 4:03:02 PM11/2/08
to

Right on. Definitions entered into the repl *are* indeed expanded and
evaluated separately and sequentially as they're entered. There is no
technical reason why they cannot be made available at expand-time code
just as well as run-time code. Adding the restriction to Ikarus to
disallow such references is a trivial exercise in enforcing arbitrary
restrictions, which I won't do of course, just like how I won't force
an error when a syntax definition, an expand-time binding, is used at
expand time.

Aziz,,,

Abdulaziz Ghuloum

unread,
Nov 2, 2008, 4:13:14 PM11/2/08
to
andreu...@yahoo.com wrote:

> Well, the explicit phase model of PLT (and Larceny) were
> invented precisely to prevent this kind of confusion. It is
> generally a bad idea, when avoidable, for the same code to
> behave differently when compiled than it would in a REPL.
> Matthew Flatt wrote a good paper on this issue years ago.

Matthew's paper was more of a critique of how programs without
modules used to be compiled and the errors that ones gets into
when trying to compile a program that runs fine in the repl.
I agree with all of that. Indeed, the only things that can be
compiled in Ikarus are libraries, which have better properties
when it comes to separate compilations. Ikarus neither does,
nor ever will attempt to compile repl interactions because that
makes no sense. The repl in my view is a cute little calculator
in which you can type your little factorial program and run it.
It was never meant to have separate-compilation semantics, so
why force library semantics to it? Other things in which the
repl differs from libraries are (1) intermixing definitions and
expressions, (2) allowing multiple definitions/redefinitions of
the same variable, (3) continuation semantics, among others.

Does Larceny/PLT provide exactly 1-to-1 correspondence between
their library semantics and repl semantics? I doubt it.

Aziz,,,

andreu...@yahoo.com

unread,
Nov 2, 2008, 5:36:43 PM11/2/08
to
On Nov 1, 11:44 pm, Michele Simionato <michele.simion...@gmail.com>
wrote:

> There is something I have always wanted to ask about Computer Science
> papers. It seems that if I want to read the paper I must subscribe to
> the site and to buy it. That looks strange to me, since I am used to
> the publication system we use in Physics.
> You must pay for peer-reviewed papers appeared in formal publications
> (actually it is the University which pays the
> subscription) however in practice nobody reads the published
> versions, because he has already read the preprint.
> Virtually all papers appears as preprint, freely downloadable

> from the xxx archives (for instance fromhttp://xxx.lanl.gov/form/hep-th


> for Theoretical Physics). Preprints appear months before the official
> publication, so people wanting to stay updated look at the preprints,
> not at the formal publications. The formal publications are still
> important, but only because they have much more value in your CV than
> a preprint.
> Is there something like that for Computer Science publications?
> How commonly used is it?

The arxiv itself has a section for computer science at
http://arxiv.org/corr/home, but it does not seem to have
been used as extensively.

As a fellow Physicist, I am continually dumbfounded and
frustrated by the inability of CS people to organize a
useful centralized preprint repository like the one we
Physicists have had for decades now (or even just to use
the one we made for them, or as a last resort just to post
preprints of their own papers on their homepages where
Google can find them).

I mean, for heavens sake, guys, you are computer scientists!
Get with the program already and learn to use the internet!

Andre

andreu...@yahoo.com

unread,
Nov 2, 2008, 5:40:54 PM11/2/08
to
On Nov 2, 12:49 pm, Abdulaziz Ghuloum <aghul...@cee.ess.indiana.edu>
wrote:

Yes, because it does not generalize.

Andre

andreu...@yahoo.com

unread,
Nov 2, 2008, 5:51:52 PM11/2/08
to
On Nov 2, 8:19 am, Abdulaziz Ghuloum <aghul...@cee.ess.indiana.edu>
wrote:


> It's a little more interleaved than that.  In definitions context
> (e.g., top-level program, library top-level, internal definitions),
> it processes the body forms one by one looking for definitions.  If
> it encounters a define-syntax, the right-hand-side is expanded and
> evaluated and made available for expanding subsequent forms from
> that point on.  If it encounters a macro use, it expands the macro,
> splices it in place of the input form and resumes with the resulting
> body forms.  If it encounters a variable definition, it does NOT
> expand the right-hand-side expression, instead, it queues it until
> all definitions (variables and macros) are found.  At that point,
> the body expressions and right-hand-side expressions of variable
> definitions (that were queued) are expanded.

Do you plan to put some version of whatever model
is described in your paper online somewhere where regular people
can get at it without paying? It seems rather pointless to
continue this discussion otherwise, since we don't know what
we are comparing against.

Andre

Abdulaziz Ghuloum

unread,
Nov 2, 2008, 6:19:02 PM11/2/08
to

What I mentioned above is not related to the paper. It is pretty
much what R6RS's expansion process says in:
http://www.r6rs.org/final/html/r6rs/r6rs-Z-H-13.html#node_chap_10

As for the paper, I will try to find out how to obtain permission
to redistribute it, given that it has a "Copyright (c) 2007 ACM"
on it.

Aziz,,,

William D Clinger

unread,
Nov 2, 2008, 7:30:35 PM11/2/08
to
Eli Barzilay wrote:
> I know that you get that error if you're not on the REPL -- but at a
> minimum, I would expect the *same* error at the REPL. (Translation:
> if I were using Ikarus, I would report the lack of error on the REPL
> as a bug.)

The R6RS editors have explicitly denied that the R6RS
says anything at all concerning the behavior of a REPL
[1]. Except for Larceny, which provides REPLs that
conform to the R5RS or ERR5RS standards, no existing
implementations of the R6RS provide a REPL that
conforms to any implementation-independent semantics.

From those facts, it follows that people who report
a bug involving the behavior of *any* pseudo-R6RS
REPL (aside from Larceny's ERR5RS mode) are relying
on nothing more than their own personal prejudices.

Will

[1] R6RS editors. Non-normative appendices to the
R6RS, chapter 8.

William D Clinger

unread,
Nov 2, 2008, 7:47:59 PM11/2/08
to
Sorry, my citation was incorrect. It should have
been:

[1] Michael Sperber, R Kent Dybvig, Matthew Flatt,
Anton van Straaten. R6RS Rationale, chapter 8.

Abdulaziz Ghuloum

unread,
Nov 2, 2008, 7:51:54 PM11/2/08
to
Eli Barzilay wrote:

> The right-hand-side of a `define-syntax' is at the syntax phase, and
> syntax-phase functions are available to it. But if you want to write
> a macro (double, in your case) that uses a macro (sub) in its body
> (not in its result), then you're getting to the second (meta-meta)
> level up. Here's an example that demonstrates conflating the meta and
> meta-meta levels in Ikarus:
>
> (define-syntax m1
> (let ([c 0])
> (lambda (stx)
> (set! c (+ c 1))
> (syntax-case stx ()
> [(_) (with-syntax ([c c]) #'c)]))))
> (define-syntax m2
> (lambda (stx)
> (syntax-case stx ()
> [(_) (let ([c (m1)])
> (with-syntax ([c c]) #'c))])))
> (display (m1))
> (display (m2))

Well, this "conflation of the meta and the meta-meta" is not related
to ikarus's implicit phasing semantics, but is rather due to the fact
that ikarus has instantiates each library once and exactly once for
all levels.

Larceny, which follows the same explicit phasing rule (i.e., the user
has to specify eval-when for imports) as plt also happens to conflate
the meta with the meta-meta. Try the following in "larceny -err5rs":

(library (M1)
(export m1)
(import (rnrs))


(define-syntax m1
(let ([c 0])
(lambda (stx)
(set! c (+ c 1))
(syntax-case stx ()

[(_) (with-syntax ([c c]) #'c)])))))

(library (M2)
(export m2)
(import (rnrs) (for (M1) expand))


(define-syntax m2
(lambda (stx)
(syntax-case stx ()
[(_) (let ([c (m1)])

(with-syntax ([c c]) #'c))]))))

(import (M1) (M2) (rnrs))

(display (m1)) ;;; displays 2
(display (m2)) ;;; displays 1


That's the same behavior as ikarus, and the similarity of behavior
between larceny and ikarus would continue even if the libraries are
separately compiled.

Conclusion: phase specification (as in the "for" syntax of r6rs
libraries) is orthogonal to phase separation (as in libraries have
different instances at different levels).[*]

So, take plt, remove the multiple instantiation, and you get larceny.
Take larceny, remove the explicit "for" syntax, and you get ikarus.
There is no such thing as the "plt/larceny" semantics.

It is also possible to design a system in which phase specification
is optional, but which instantiates libraries afresh at different
levels, but no one has done that to date.

Aziz,,,


[*] This conclusion is nothing new of course. I'm just trying to
highlight the similarities and differences between the different
systems, and try to separate the different issues that are often
lumped together under the "phased"/"unphased" labels.

Abdulaziz Ghuloum

unread,
Nov 2, 2008, 8:01:59 PM11/2/08
to
William D Clinger wrote:

> The R6RS editors have explicitly denied that the R6RS
> says anything at all concerning the behavior of a REPL
> [1]. Except for Larceny, which provides REPLs that
> conform to the R5RS or ERR5RS standards,

I don't remember R5RS specifying semantics for the REPL;
and I don't remember ERR5RS being a standard.

Mimicking the Monty Python:
ERR5RS: I am your king
Woman: Well, I didn't vote for you!
ERR5RS: You don't vote for kings.
Woman: Well how'd you become king then?
...

> no existing
> implementations of the R6RS provide a REPL that
> conforms to any implementation-independent semantics.

That is correct, for the lack of such specifications of
semantics, yes.

> From those facts, it follows that people who report
> a bug involving the behavior of *any* pseudo-R6RS
> REPL (aside from Larceny's ERR5RS mode) are relying
> on nothing more than their own personal prejudices.

That too is correct.

Aziz,,,

William D Clinger

unread,
Nov 2, 2008, 8:57:37 PM11/2/08
to
Aziz wrote:
> I don't remember R5RS specifying semantics for the REPL;

With so many things to remember, it's easy to forget
things. The R5RS *doesn't* specify any *required*
semantics for REPLs, but it *does* specify semantics
for programs (in chapter 5 and section 7.2) that are
compatible with REPLs, and chapter 5 explicitly says
that "Programs are typically stored in files or
entered interactively to a running Scheme system...".

Implementations of the R5RS are not required to provide
a REPL that implements the R5RS semantics for programs,
but many implementations of the R5RS do in fact provide
such a REPL. In particular, Larceny does, and I believe
PLT Scheme does also.

The R6RS, on the other hand, does not specify any
semantics that would be compatible with a REPL. In
the R6RS, all pieces of a program must be collected
together and subjected to certain static checks
before any portion of the program is allowed to
execute, from which it follows that the R6RS cannot
be implemented using a read/eval/print loop.

ERR5RS specifies a REPL-compatible semantics that
is also largely compatible with the R6RS program
semantics (except that some of the static checks
become dynamic, of course). That's one of the main
contributions of ERR5RS: it demonstrates the technical
feasibility of specifying implementation-independent
semantics for REPLs that are largely compatible with
both the R5RS and R6RS semantics.

The R6RS subculture may not wish to recognize any
implementation-independent semantics that could
unify R5RS-style REPLs with R6RS-style libraries,
but that would be a political calculation, not a
technical decision.

Will

Derick Eddington

unread,
Nov 2, 2008, 11:56:47 PM11/2/08
to
On Nov 2, 10:56 am, Eli Barzilay <e...@barzilay.org> wrote:
> On Nov 2, 6:31 am, Michele Simionato <michele.simion...@gmail.com>
> wrote:
> > On Nov 2, 11:45 am, leppie <xacc....@gmail.com> wrote:
>
> > > The lack of the expected error is due to REPL.

> > Indeed.


>
> [I should have been clearer about my example, but due to other reasons
> preferred to avoid making my reply longer.]

Eli's example is applicable to R6RS-official top-level programs and
libraries. I think reformulating it might help others see what's
being discussed about the two different issues of phase specification
and library instances.

;;;;;;;;;;;;;;;;;;;;;;; temp/count.sls ;;;;;;;;;;;;;;;;;;;;;
#!r6rs
(library (temp count)
(export count!)
(import (rnrs))
(define count!


(let ([c 0])

(display "count!\n")
(lambda ()
(set! c (+ 1 c))
c)))
(display "library (temp count)\n"))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;; temp/use-count.sps ;;;;;;;;;;;;;;;;;
#!r6rs
(import
(rnrs)
;; "for" part unnecessary for and ignored in Ikarus
(for (temp count) run expand))
(define-syntax foo
(begin
(display "foo\n")


(lambda (stx)
(syntax-case stx ()

[(_ name)
(with-syntax ([c (count!)])

#'(define (name) (list c (count!))))]))))
(foo bar)
(write (bar)) (newline)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

[d@eep:~/zone/scheme]-> ikarus --r6rs-script temp/use-count.sps
count!
library (temp count)
foo
(1 2)
[d@eep:~/zone/scheme]-> mzscheme temp/use-count.sps
count!
library (temp count)
foo
count!
library (temp count)
count!
library (temp count)
foo
(1 1)
[d@eep:~/zone/scheme]-> larceny -path . -r6rs -program temp/use-
count.sps
count!
library (temp count)
foo
(1 2)
[d@eep:~/zone/scheme]->

When the (temp count) library is instantiated, an instance of the
count! variable and an instance of the c variable that count! closes
over are created. If this library is instantiated at most once, the
same count! and therefore the same c variable are always used whenever
count! is called, regardless of the phase (run-time, expand-time, or
higher) it's being used for, and so we get (1 2) with Ikarus and
Larceny. If this library is instantiated every time it's needed, then
there are distinct instances of these variables, and so we get (1 1)
with MzScheme.

This is related to what Aziz said:

On Nov 2, 4:51 pm, Abdulaziz Ghuloum <aghul...@cee.ess.indiana.edu>
wrote:


> phase specification (as in the "for" syntax of r6rs
> libraries) is orthogonal to phase separation (as in libraries have
> different instances at different levels).
>

> So, take plt, remove the multiple instantiation, and you get larceny.
> Take larceny, remove the explicit "for" syntax, and you get ikarus.

> It is also possible to design a system in which phase specification


> is optional, but which instantiates libraries afresh at different
> levels, but no one has done that to date.

Because mutable state is a tricky thing, I think Eli is concerned that
not having separate instantiations of libraries could lead to more
risks/difficulties of dealing with mutable state. But I see this
count! example as no more dangerous than dealing with mutable state
that exists only at run-time -- you should not, in the first place,
have told it to use count! at expand-time and run-time, unless that's
what you really wanted. The same type of mistake can just as easily
be made with only-at-run-time code and there's no way of avoiding that
(in normal Scheme). It makes sense to me the bindings one says to
import should be the same regardless of when they're used. If you
need something different at expand-time versus run-time, you should
name them differently, meaning you should use something different,
which seems a lot less confusing. Now of course, Eli's example is a
super simplification of real issues of state in libraries/modules PLT
deals with. But when I think about trying to deal with mutable state
in library instances, it seems much simpler and more manageable to
know you're only going to have one instantiation. Eli (or anyone who
knows), would you describe why multiple instantiation of libraries is
necessary or "the right way" for what PLT does with mutable library/
module state?

--
: Derick
----------------------------------------------------------------

Derick Eddington

unread,
Nov 3, 2008, 12:01:48 AM11/3/08
to
On Nov 2, 10:56 am, Eli Barzilay <e...@barzilay.org> wrote:
> On Nov 2, 6:31 am, Michele Simionato <michele.simion...@gmail.com>
> wrote:
> > Notice that in my answer to Eli I made a mistake talking about
> > helper functions when I should have said "helper macros".
>
> Your mistake is strongly related to the confusion I'm talking about.
> A macro is different from a function in that it lives in a separate
> world. In a language like C, macros are very obviously coming from a
> different world because it's written in a different language. In a
> lot of Scheme code, the language used for your macros is written the
> same language, but it's still not the same world because of the way
> they're evaluated: macros are called at compilation (aka expansion)
> time sequentially, and other functions are called at runtime; when you
> compile code the latter is never called, and when you run the result
> the former is never called.

[Snipped Eli's comment about multiple instantiations of modules and
how he uses it in PLT, which I hope will be elaborated upon.]

Thanks for describing all this, Eli. Using different languages for
different phases is an interesting idea. It looks like implicit
phasing would do it in a way that seems clearer to me by requiring
preventing identifier conflicts. In the below, the prefixing isn't
actually necessary because there are no conflicts, but it shows the
idea for if there were conflicts:

(library (insane-freak)
(export foo)
(import
(prefix (rnrs) rnrs:)
(prefix (my-lang) my:)) ;; assuming implicit phasing
(rnrs:define-syntax foo
(my:function (stx)
(my:bind ([l (my:destructure stx)])
(my:list-prefix (rnrs:syntax rnrs:+) l)))))


Why do we need explicit phase specification to use different languages
for different phases?

--
: Derick
----------------------------------------------------------------

Derick Eddington

unread,
Nov 3, 2008, 12:16:35 AM11/3/08
to
On Nov 2, 9:01 pm, Derick Eddington <derick.edding...@gmail.com>
wrote:

> Thanks for describing all this, Eli.  Using different languages for
> different phases is an interesting idea.  It looks like implicit
> phasing would do it in a way that seems clearer to me by requiring
> preventing identifier conflicts.

To correct myself, as has already been discussed, R6RS already
requires preventing identifier conflicts regardless of the phasing
model. So using the import modifiers to avoid conflicts is always
necessary.

--
: Derick
----------------------------------------------------------------

Derick Eddington

unread,
Nov 3, 2008, 12:25:20 AM11/3/08
to

I haven't realized why this is cheating because it does not
generalize. What is it the explicit phasing design can do that the
implicit one cannot?

--
: Derick
----------------------------------------------------------------

Michele Simionato

unread,
Nov 3, 2008, 12:50:37 AM11/3/08
to
On Nov 3, 1:51 am, Abdulaziz Ghuloum <aghul...@cee.ess.indiana.edu>
wrote:

Finally I begin to see the light. I tried exactly this example in PLT,
and it displays 11, not 21. At first I was surprised, but now I think
I understand what you mean by multiple instantiation of libraries. In
PLT I wrote the example in
a directory called eli-example with a main.ss script like
the following:

#!r6rs
(library (eli-example)
(export m1 m2)
(import (rnrs) (eli-example M1) (eli-example M2)))

Here the module M1 is imported, the value of c is set to 1,
and m1 is exported again, with (m1) equal to 1. The fact that
internally M2 imports M1 another time has no effect at all. In Ikarus/
Larceny instead modules are like shared singletons:
if module M2 increments the counter, the effect is visible from the
outside. So, in principle PLT system is better, I will concede that.
On the other hand, Ikarus system is simpler, and once users are warned
of the dangers of stateful macros, I think people can live with them.
BTW, I would you write a compile time register in PLT, i.e. a global
storage of names working across modules?

Michele Simionato

Abdulaziz Ghuloum

unread,
Nov 3, 2008, 12:51:43 AM11/3/08
to
Derick Eddington wrote:

> Using different languages for different phases is an interesting
> idea.

Yes Derick. It is interesting. Even more interesting is using
different languages at the same phase; say mixing typed scheme
with untyped scheme, or mixing lazy scheme with strict scheme.
This by itself is interesting, and there is much research going
on by the PLT members in this area (which is good).

However, the problem of how different languages interact is hardly
related to macros, libraries, import levels, library instantiation,
and such issues. Yes, they may affect how one would implement
these features (like typed scheme) if it were to be implemented as
a set of scheme macros; but this is an implementation detail and
an artifact of how one implementation of typed scheme was conceived
at the time. It is irrelevant in the long run, say, if typed scheme
takes over the scheme world and we end up implementing it as the
default language. Then, again, and as always, implicit phasing
would continue to be relevant.


> (library (insane-freak)
> (export foo)
> (import
> (prefix (rnrs) rnrs:)
> (prefix (my-lang) my:)) ;; assuming implicit phasing
> (rnrs:define-syntax foo
> (my:function (stx)
> (my:bind ([l (my:destructure stx)])
> (my:list-prefix (rnrs:syntax rnrs:+) l)))))
>
>
> Why do we need explicit phase specification to use different languages
> for different phases?

One can argue that prefixing like this makes the code ugly. Others
will argue that it makes the intent of the code clear. There is no
right answer. The question to you, Derick, since you've written and
ported so many R6RS libraries so far (maybe more than the rest of us
combined) is: How many times did you need to restrict bindings to
one level or another? And have you ever been bitten by Ikarus's
implicit phasing semantics? (other than when trying to run your
code under plt and realizing that it didn't work of course)

Aziz,,,

William D Clinger

unread,
Nov 3, 2008, 12:56:01 AM11/3/08
to
Derick Eddington asked:

> But when I think about trying to deal with mutable state
> in library instances, it seems much simpler and more manageable to
> know you're only going to have one instantiation.

True.

> Eli (or anyone who
> knows), would you describe why multiple instantiation of libraries is
> necessary or "the right way" for what PLT does with mutable library/
> module state?

It isn't necessary. With Larceny's semantics, you
can obtain the effect of the PLT semantics by
duplicating libraries. With the PLT semantics,
however, you cannot obtain the effect of Larceny's
semantics.

That means Larceny's semantics is more expressive
than the PLT semantics. That doesn't mean Larceny's
semantics is "the right way", but it does prove that
the PLT semantics is not the only way to obtain the
behavior Eli prefers.

In short: Multiple instantiation of libraries is
unnecessary, even for Eli's examples.

Will

Abdulaziz Ghuloum

unread,
Nov 3, 2008, 1:21:51 AM11/3/08
to
Michele Simionato wrote:

> Finally I begin to see the light. I tried exactly this example in PLT,
> and it displays 11, not 21. At first I was surprised, but now I think
> I understand what you mean by multiple instantiation of libraries. In
> PLT I wrote the example in
> a directory called eli-example with a main.ss script like
> the following:
>
> #!r6rs
> (library (eli-example)
> (export m1 m2)
> (import (rnrs) (eli-example M1) (eli-example M2)))
>
> Here the module M1 is imported, the value of c is set to 1,
> and m1 is exported again, with (m1) equal to 1. The fact that
> internally M2 imports M1 another time has no effect at all. In Ikarus/
> Larceny instead modules are like shared singletons:
> if module M2 increments the counter, the effect is visible from the
> outside. So, in principle PLT system is better, I will concede that.
> On the other hand, Ikarus system is simpler, and once users are warned
> of the dangers of stateful macros, I think people can live with them.
> BTW, I would you write a compile time register in PLT, i.e. a global
> storage of names working across modules?

All correct and good observations. Here are more questions that I would
like answered about this multiple instantiation of libraries.

1. How does the PLT model answer to side effects that are not simple
side effects like set!? (e.g., operations on the file system,
performing remote operations, etc.)

2. How would one maintain large databases (say unicode tables) in a
library without replicating resources over and over again at all
these different phases?

3. Does mzscheme really instantiate all of the (rnrs) libraries at
all phases in which they are imported? Or does it take some
shortcuts for efficiency by phase shifting the bindings?

4. How would one instantiate external resources (like foreign code)
at different phases when such notion of library instantiation
does not exist outside of mzscheme? Even if I were to do that,
how does a Scheme library know in which phase it is being
instantiated?

5. Are there different (current-input-port), (current-output-port),
(current-error-port), different sets of dynamic-wind winders,
different sets of exception handlers, etc., at different phases?
How do they interact?

6. Suppose you forward the standard input/output ports to a gui
window, where the code of that gui window is in some library.
If such ports are used at both expand time and run time, how
many gui windows will be opened?

7. In what phases are libraries obtained from (environment ---)
instantiated? Are they the same or different from the set of
libraries instantiated for run, expand, meta-2, etc.? Would
calling (environment '(foo)) twice cause two different instances
or foo, or just one? What about calling (environment '(foo))
from different phases? What about calling (environment '(foo))
from within eval itself? Does recursive calls to eval and
environment cause instantiation of arbitrary number of
instances?

All of these questions have a trivial answer when the number of
instances of each library is 1 and when that same instance is
used for run, expand, meta-n, eval, and so on. All of them
become very hard when you have multiple instances, and when you
have little or no control over these instances (which is the
essence of separation: if separate instances can observe being
separate, then you have no separation at all).

Aziz,,,

Eli Barzilay

unread,
Nov 3, 2008, 1:23:01 AM11/3/08
to
Derick Eddington <derick.e...@gmail.com> writes:

Make `syntax-rules' and one other binding. Or two more. etc.

Eli Barzilay

unread,
Nov 3, 2008, 1:24:16 AM11/3/08
to
Abdulaziz Ghuloum <aghu...@cee.ess.indiana.edu> writes:

> andreu...@yahoo.com wrote:
>
>> Well, the explicit phase model of PLT (and Larceny) were
>> invented precisely to prevent this kind of confusion. It is
>> generally a bad idea, when avoidable, for the same code to
>> behave differently when compiled than it would in a REPL.
>> Matthew Flatt wrote a good paper on this issue years ago.
>
> Matthew's paper was more of a critique of how programs without
> modules used to be compiled and the errors that ones gets into
> when trying to compile a program that runs fine in the repl.

That's a gross misunderestimation of the paper.

Eli Barzilay

unread,
Nov 3, 2008, 1:25:52 AM11/3/08
to
Abdulaziz Ghuloum <aghu...@cee.ess.indiana.edu> writes:

> Adding the restriction to Ikarus to disallow such references is a
> trivial exercise in enforcing arbitrary restrictions, which I won't
> do of course, just like how I won't force an error when a syntax
> definition, an expand-time binding, is used at expand time.

(Note how the implict number-to-string coercion analogy is still
valid.)

Eli Barzilay

unread,
Nov 3, 2008, 1:27:26 AM11/3/08
to
William D Clinger <cesu...@yahoo.com> writes:

> Eli Barzilay wrote:
>> I know that you get that error if you're not on the REPL -- but at
>> a minimum, I would expect the *same* error at the REPL.
>> (Translation: if I were using Ikarus, I would report the lack of
>> error on the REPL as a bug.)
>
> The R6RS editors have explicitly denied that the R6RS
> says anything at all concerning the behavior of a REPL

The point was not the repl semantics -- it was the general facility
that has lead to that error. (Which I later redemonstrated in a
library by lifting the example up to the meta level.)

Eli Barzilay

unread,
Nov 3, 2008, 1:32:51 AM11/3/08
to
Abdulaziz Ghuloum <aghu...@cee.ess.indiana.edu> writes:

> Eli Barzilay wrote:
>
>> The right-hand-side of a `define-syntax' is at the syntax phase,
>> and syntax-phase functions are available to it. But if you want to
>> write a macro (double, in your case) that uses a macro (sub) in its
>> body (not in its result), then you're getting to the second
>> (meta-meta) level up. Here's an example that demonstrates
>> conflating the meta and meta-meta levels in Ikarus:
>>
>> (define-syntax m1
>> (let ([c 0])
>> (lambda (stx)
>> (set! c (+ c 1))
>> (syntax-case stx ()
>> [(_) (with-syntax ([c c]) #'c)]))))
>> (define-syntax m2
>> (lambda (stx)
>> (syntax-case stx ()
>> [(_) (let ([c (m1)])
>> (with-syntax ([c c]) #'c))])))
>> (display (m1))
>> (display (m2))
>
> Well, this "conflation of the meta and the meta-meta" is not related
> to ikarus's implicit phasing semantics,

The conflation is the implicit phasing, and the availability of a
macro to both runtime and macro code. I just used state to highlight
it. (Of course I cannot use different bindings for the same names if
I want the example to work with the r6rs restriction.)


> [*] This conclusion is nothing new of course. I'm just trying to
> highlight the similarities and differences between the different
> systems, and try to separate the different issues that are often
> lumped together under the "phased"/"unphased" labels.

Right. I view both of this as potential problems.

Michele Simionato

unread,
Nov 3, 2008, 1:33:39 AM11/3/08
to
On Oct 26, 11:46 am, Michele Simionato <michele.simion...@gmail.com>
wrote:
There is another issue with the porting of sweet-macros to PLT
and I would like to ask the help of Eli and other PLT experts here.
If you install the library (https://www.phyast.pitt.edu/~micheles/
scheme/sweet-macros.zip)
and you try to run this code

$ cat hello.ss
#!r6rs
(import (rnrs) (sweet-macros))
(def-syntax (hello) #'(display "hello world!"))
(display (syntax-expand (hello)))

you get the following error:

$ plt-r6rs hello.ss
/home/micheles/.plt-scheme/4.0/collects/sweet-macros/helper1.sls:
56:11: compile: bad syntax; reference to top-level identifier is not
allowed, because no #%top syntax transformer is bound in: syntax-match

What does it mean and how I fix it? Of course, everything works in
Ikarus.

tom.g...@me.com

unread,
Nov 3, 2008, 1:35:40 AM11/3/08
to
That was a very long way to concede Aziz's point: There was no
standard for REPLs in R5RS and there still is no standard for REPLs in
R6RS.

But that doesn't mean a REPL couldn't become part of some future
RnRS. This sounds like a good issue for R7RS and maybe a reason to
get involved.

-Tom

Eli Barzilay

unread,
Nov 3, 2008, 1:45:50 AM11/3/08
to
Michele Simionato <michele....@gmail.com> writes:

> Here the module M1 is imported, the value of c is set to 1,
> and m1 is exported again, with (m1) equal to 1. The fact that
> internally M2 imports M1 another time has no effect at all.

Yes, that's the multiple instantiations aspect.


> In Ikarus/ Larceny instead modules are like shared singletons: if
> module M2 increments the counter, the effect is visible from the
> outside.

Specifically, order of compilation might affect the result.


> So, in principle PLT system is better, I will concede that. On the
> other hand, Ikarus system is simpler, and once users are warned of
> the dangers of stateful macros, I think people can live with them.

Actually, having a new instace of the syntax-phase world for each
module compilation means that you can now use guranteed-to-be-fresh
state -- the result is still reliable and deterministic.


> BTW, I would you write a compile time register in PLT, i.e. a global
> storage of names working across modules?

(I assume that you menat "how would".) The real beauty of this
approach (IMO, I'll repeat for the Nth time, just in case) is that
things that are difficult or impossible to do are actually things that
you shouldn't do. For example, having such a global name register
should be done in a way that still expands (and compiles) to the same
code, regardless of the order of compiled modules, or whether other
modules were even compiled in the same batch. It is therefore fine to
have such kind of registration be reset for every module separately.
(This is not different than using a single-instace system and
compiling each file by itself (assuming no shared state between
different phases).)

By the way -- back when PLT switched to separated phases I was
maintaining Swindle, which was a relatively large piece of code.
Being rich in macros, some of them can be easily made to depend on
runtime state, I was extremely unhappy with the move -- my initial
perception of this was that got one arm tied behind my back now. Only
when I went through the porting process I realized that it's all
making perfect sense. My main conclusion of that experience is that
it is easy to miss the advantages if you don't actually use them.

Abdulaziz Ghuloum

unread,
Nov 3, 2008, 1:57:51 AM11/3/08
to
Michele Simionato wrote:

> $ plt-r6rs hello.ss
> /home/micheles/.plt-scheme/4.0/collects/sweet-macros/helper1.sls:
> 56:11: compile: bad syntax; reference to top-level identifier is not
> allowed, because no #%top syntax transformer is bound in: syntax-match
>
> What does it mean and how I fix it? Of course, everything works in
> Ikarus.

The %app error can be fixed by changing the import in helper1.ss to be

(import (for (rnrs) (meta -1) run expand))

But even doing so does not solve your problem because then you get:

sweet-macros/helper1.sls:56:11: compile: unbound variable in module in:
syntax-match


The culprit here is the following code:

(define-syntax syntax-match
(lambda (x)
(syntax-case x (sub)
((_ (literal ...) (sub patt skel . rest) ...)
#'(lambda (x)
(syntax-match x (literal ...)
(sub patt skel . rest) ...)))
---))

Basically, your syntax-match macro is trying to phase-shift itself
into the next level! I have been trying for more than a year to
find a real life (not a contrived) example of a macro that actually
expands to a use of itself at the next level, and failed. And now
you come and throw it at my lap. Thanks!

And no, I can't help you fix it. :-)

Aziz,,,

Eli Barzilay

unread,
Nov 3, 2008, 2:02:10 AM11/3/08
to
Derick Eddington <derick.e...@gmail.com> writes:
>
> [...] But I see this count! example as no more dangerous than

> dealing with mutable state that exists only at run-time -- you
> should not, in the first place, have told it to use count! at
> expand-time and run-time, unless that's what you really wanted. The
> same type of mistake can just as easily be made with
> only-at-run-time code and there's no way of avoiding that (in normal
> Scheme).

That's correct -- you should always be careful when you use state,
specifically, in runtime code you need to make sure that you know
where the state is initialized. Without multiple instantiations this
doesn't hold for state used in macros -- but when you add multiple
instantiations then you know that each module compilation starts in an
initial state.


> It makes sense to me the bindings one says to import should be the
> same regardless of when they're used.

This is a different issue, which I wrote about elsewhere in this
thread.


> If you need something different at expand-time versus run-time, you
> should name them differently, meaning you should use something
> different, which seems a lot less confusing.

[The result is going to be horribly verbose. More than that -- given
a syntax system as rich as PLT's, this means also specifiying prefixed
macro names in all function applications, variable references, and
several other implicit macros that you don't usually type explicitly.]


> Now of course, Eli's example is a super simplification of real
> issues of state in libraries/modules PLT deals with. But when I
> think about trying to deal with mutable state in library instances,
> it seems much simpler and more manageable to know you're only going
> to have one instantiation.

[You're back to the state issue now.]

There is also the state that is implicit in things like new struct
definitions. If I ever make a mistake and plant a swindle object in
the resulting syntax of a macro, (for example, something like
#`(quote ,(make <foo>))), then what happens is that the runtime value
of this expression is not going to be considered an instance --
because that uses a different swindle system. (And this is related to
the fact that such a macro will produce code that cannot be marshaled
to a compiled file.)


> Eli (or anyone who knows), would you describe why multiple
> instantiation of libraries is necessary or "the right way" for what
> PLT does with mutable library/ module state?

[I don't know what description you expect. Hopefully the above helps
clarifying.]

Abdulaziz Ghuloum

unread,
Nov 3, 2008, 2:02:19 AM11/3/08
to
Abdulaziz Ghuloum wrote:

> The culprit here is the following code:

Let me temporarily retract my analysis. It might not be correct.
Sorry, I got excited.

Aziz,,,

Eli Barzilay

unread,
Nov 3, 2008, 2:06:49 AM11/3/08
to
William D Clinger <cesu...@yahoo.com> writes:

> Derick Eddington asked:


>
>> Eli (or anyone who knows), would you describe why multiple
>> instantiation of libraries is necessary or "the right way" for what
>> PLT does with mutable library/ module state?
>
> It isn't necessary. With Larceny's semantics, you can obtain the
> effect of the PLT semantics by duplicating libraries.

How is such duplication achieved?


> With the PLT semantics, however, you cannot obtain the effect of
> Larceny's semantics.

Right. So far I didn't see an example where this restriction was in
my way -- I believe that cases that exploit this extra ability in
Larceny are potential bugs (IOW, these cases create
order-of-compilation problems).

Abdulaziz Ghuloum

unread,
Nov 3, 2008, 2:11:13 AM11/3/08
to

No, that was right. Here it is; and don't ask why.

Aziz,,,

(define-syntax syntax-match
(lambda (x)
(syntax-case x (sub)

((syntax-match-in-current-phase (literal ...) (sub patt skel .

rest) ...)
#'(lambda (x)

(syntax-match-in-current-phase x (literal ...)


(sub patt skel . rest) ...)))

((syntax-match-in-current-phase x (literal ...) (sub patt skel .
rest) ...)
(and (identifier? #'x) (for-all identifier? #'(literal ...)))
#'(guarded-syntax-case x
(<literals> <patterns> <source> <transformer> literal ...)
((ctx <literals>) #''((... (... literal)) ...))
((ctx <patterns>) #''((... (... patt)) ...))
((ctx <source>)
#''(syntax-match (literal ...)
(... (... (sub patt skel . rest))) ...))
((ctx <transformer>)
#'(syntax-match-in-current-phase (literal ...)
(... (... (sub patt skel . rest))) ...))
(patt skel . rest) ...))
)))

Eli Barzilay

unread,
Nov 3, 2008, 2:13:57 AM11/3/08
to
Derick Eddington <derick.e...@gmail.com> writes:

> Thanks for describing all this, Eli. Using different languages for
> different phases is an interesting idea. It looks like implicit
> phasing would do it in a way that seems clearer to me by requiring
> preventing identifier conflicts. In the below, the prefixing isn't
> actually necessary because there are no conflicts, but it shows the
> idea for if there were conflicts:
>
> (library (insane-freak)
> (export foo)
> (import
> (prefix (rnrs) rnrs:)
> (prefix (my-lang) my:)) ;; assuming implicit phasing
> (rnrs:define-syntax foo
> (my:function (stx)
> (my:bind ([l (my:destructure stx)])
> (my:list-prefix (rnrs:syntax rnrs:+) l)))))

A side comment: When I talk about a different language I mean
something that goes further than just adding some bindings -- I'm
talking about having a different binding for things like `define',
`let', and `begin'; and further -- things like PLT's `#%app' and
`#%top'. These are all crucial components in making languages like
frtime, typed scheme, and lazy scheme.

[And this is of course unrelated to r6rs and to ikarus.]

Eli Barzilay

unread,
Nov 3, 2008, 2:20:53 AM11/3/08
to
Abdulaziz Ghuloum <aghu...@cee.ess.indiana.edu> writes:

> Derick Eddington wrote:
>
>> Using different languages for different phases is an interesting
>> idea.
>
> Yes Derick. It is interesting. Even more interesting is using
> different languages at the same phase; say mixing typed scheme
> with untyped scheme, or mixing lazy scheme with strict scheme.
> This by itself is interesting, and there is much research going
> on by the PLT members in this area (which is good).

This is actually something that you can get with Ikarus too -- all you
need is to write typed scheme code in one module and lazy scheme code
in another. (But as I mentioned earlier, being able to implement such
languages depend on other features of the implementation that Ikarus
doesn't have..)

Abdulaziz Ghuloum

unread,
Nov 3, 2008, 2:27:35 AM11/3/08
to

I don't know Tom, it doesn't look too promising. Given all the
disagreements on library semantics (which is the simpler of the
two), and how wildly different Scheme REPLs differ in their
semantics, I don't see hope in reaching unified REPL semantics.
(but don't let me discourage you; it's worth a shot, maybe)

Abdulaziz Ghuloum

unread,
Nov 3, 2008, 2:32:03 AM11/3/08
to
Eli Barzilay wrote:

> (But as I mentioned earlier, being able to implement such languages
> depend on other features of the implementation that Ikarus doesn't have
> ..)

Oh don't underestimate what Ikarus has under its wings. :-)
Ikarus, as a shy implementation, exposes less than half of its
potential, and then leaves some.

Aziz,,,

Abdulaziz Ghuloum

unread,
Nov 3, 2008, 2:37:43 AM11/3/08
to
Abdulaziz Ghuloum wrote:

> I don't know Tom, it doesn't look too promising. Given all the
> disagreements on library semantics (which is the simpler of the
> two), and how wildly different Scheme REPLs differ in their
> semantics, I don't see hope in reaching unified REPL semantics.

(reminder to self: stop saying semantics)

Eli Barzilay

unread,
Nov 3, 2008, 2:49:27 AM11/3/08
to
Abdulaziz Ghuloum <aghu...@cee.ess.indiana.edu> writes:

> All correct and good observations. Here are more questions that I
> would like answered about this multiple instantiation of libraries.
>
> 1. How does the PLT model answer to side effects that are not simple
> side effects like set!?

[I've mentioned also creating new struct types, which results in
different phases having incompatible values.]


> (e.g., operations on the file system, performing remote
> operations, etc.)

Such state is as broken as it is anywhere, and there obviously isn't
much anyone can do about this more than forbidding such `external'
mutations. But `set!'-style state is reliable, which is why this is a
feature.


> 2. How would one maintain large databases (say unicode tables) in a
> library without replicating resources over and over again at all
> these different phases?

It is expensive, yes, as expensive as the cost or instantiating a
module (so, for example, code (including quoted literals) is not
regenerated). (But the extra cost is only at compile-time.)


> 3. Does mzscheme really instantiate all of the (rnrs) libraries at
> all phases in which they are imported? Or does it take some
> shortcuts for efficiency by phase shifting the bindings?

I cannot answer that in any definitive way because I didn't implement
it, but generally speaking there is no way to phase-shift bindings.
(More specifically, when you use a the plt module system you do get
your syntax-level requires to reinstantiate.)


> 4. How would one instantiate external resources (like foreign code)
> at different phases when such notion of library instantiation
> does not exist outside of mzscheme?

I'm not sure what you mean here. Two examples that I can think of: if
you're using a foreign library, then the underlying C code that
implements the ffi is making sure there is a single handle on the
external library (IOW, no phase separation at the C level); if you're
going to use some DB connection in a library that is used at syntax
time, then in the usual case you will get one such connection for each
module that gets compiled.


> Even if I were to do that, how does a Scheme library know in
> which phase it is being instantiated?

(I've never seen a need to know at which level your code is invoked.)


> 5. Are there different (current-input-port), (current-output-port),
> (current-error-port),

No -- which makes this a "back-door" similar to using the filesystem.


> different sets of dynamic-wind winders, different sets of
> exception handlers, etc., at different phases?

In some cases there are continuation barriers; exception handlers have
dynamic extent so some are specific to run time, some to syntax time,
and some are specific to both (for example, when you wrap code that
compiles a new module and runs it, for example using the sandbox
library).


> How do they interact?

(I don't know what you mean by "they interact", but if you want more
details you can just try it, or as on the plt list.)


> 6. Suppose you forward the standard input/output ports to a gui
> window, where the code of that gui window is in some library. If
> such ports are used at both expand time and run time, how many
> gui windows will be opened?

Same as in the previous item: you usually divert the IO ports for a
specific dynamic extent. Changing them globally is equivalen to using
FS state.


> 7. In what phases are libraries obtained from (environment ---)
> instantiated? Are they the same or different from the set of
> libraries instantiated for run, expand, meta-2, etc.? Would
> calling (environment '(foo)) twice cause two different instances
> or foo, or just one? What about calling (environment '(foo))
> from different phases? What about calling (environment '(foo))
> from within eval itself? Does recursive calls to eval and
> environment cause instantiation of arbitrary number of instances?

I think that the namespace documentation is relevant here.


> All of these questions have a trivial answer when the number of
> instances of each library is 1 and when that same instance is used
> for run, expand, meta-n, eval, and so on.

a. The above answers (module questions that I could not answer) are
also trivial trivial from my point of view.

b. Trivial or not, phase separation is still providing an important
feature. One that is crucial in many ways (that you don't see,
which makes my sentence a subjective observation).


> All of them become very hard when you have multiple instances, and
> when you have little or no control over these instances (which is
> the essence of separation: if separate instances can observe being
> separate, then you have no separation at all).

There is a very simple way to describe how it is achieved: to compile
a bunch of files run a separate ikarus (or larceny or whatever)
process to compile each module, then run another process to run the
result.

Eli Barzilay

unread,
Nov 3, 2008, 2:58:07 AM11/3/08
to
Abdulaziz Ghuloum <aghu...@cee.ess.indiana.edu> writes:

You are very extremely welcome to implement these languages.

Abdulaziz Ghuloum

unread,
Nov 3, 2008, 3:10:00 AM11/3/08
to
Eli Barzilay wrote:

>> 5. Are there different (current-input-port), (current-output-port),
>> (current-error-port),
>
> No -- which makes this a "back-door" similar to using the filesystem.

Okay, but this is a very useful feature that we all use everyday.
But with the phase separation, I cannot implement such facility
(like a current-sdl-window for example).

How do I implement my own "back-door"? I know I can escape to C
and stash my globals there. Is this the only way to escape the
phase separation in MzScheme?

Aziz,,,

Abdulaziz Ghuloum

unread,
Nov 3, 2008, 3:21:02 AM11/3/08
to
Eli Barzilay wrote:

>> 1. How does the PLT model answer to side effects that are not simple
>> side effects like set!?
>
> [I've mentioned also creating new struct types, which results in
> different phases having incompatible values.]

But what if I want to have the same struct types at all levels
(e.g., as required for compile-time generative record types).

How would there be a globally unique mapping from uids to record
type descriptors if all phases are separate?

Aziz,,,

Eli Barzilay

unread,
Nov 3, 2008, 3:31:23 AM11/3/08
to
Abdulaziz Ghuloum <aghu...@cee.ess.indiana.edu> writes:

> Eli Barzilay wrote:
>
>>> 5. Are there different (current-input-port), (current-output-port),
>>> (current-error-port),
>>
>> No -- which makes this a "back-door" similar to using the
>> filesystem.
>
> Okay, but this is a very useful feature that we all use everyday.
> But with the phase separation, I cannot implement such facility
> (like a current-sdl-window for example).

I don't see why -- the IO ports are implemented as parameters, which
means that you can change them for a given dynamic extent -- one where
compilation happens, or one where runtime happens. The possible
negative effect of this back door is if you read from the input port,
which can lead to breaking separate compilation -- but that's again
equivalent to using the filesystem.


> How do I implement my own "back-door"?

My experience (which includes witnessing many cases on the plt mailing
list where people tried to back-door their way to some solution) is
that if you want to implement such a back door, then most likely you're
trying to do something wrong (wrong in an objective sense, not just
wrong according to mzscheme's rules). In very rare case you're not
wrong, but then you'd be knowledgeable enough to know how to do it.
(Slight exaggeration here: I'm saying "rare" just to be safe, I don't
remember any such actual cases.)

[BTW, such discussions are similar in nature to the usual way to
approach people who are convinced that they must use `eval' -- either
they shouldn't, or they know enough to not ask about it.]


> I know I can escape to C and stash my globals there. Is this the
> only way to escape the phase separation in MzScheme?

The right way I'd advise you (for any value of "you") to go about this
is to describe what problem you're trying to solve, and most likely
the solution will not require a back door.

Eli Barzilay

unread,
Nov 3, 2008, 3:37:32 AM11/3/08
to
Abdulaziz Ghuloum <aghu...@cee.ess.indiana.edu> writes:

You mean non-generative? If so, then I think that this is the
relevant bit:

http://docs.plt-scheme.org/guide/define-struct.html#(tech._prefab)

Abdulaziz Ghuloum

unread,
Nov 3, 2008, 3:45:25 AM11/3/08
to
Eli Barzilay wrote:
> Abdulaziz Ghuloum <aghu...@cee.ess.indiana.edu> writes:
>
>> Eli Barzilay wrote:
>>
>>>> 5. Are there different (current-input-port), (current-output-port),
>>>> (current-error-port),
>>> No -- which makes this a "back-door" similar to using the
>>> filesystem.
>> Okay, but this is a very useful feature that we all use everyday.
>> But with the phase separation, I cannot implement such facility
>> (like a current-sdl-window for example).
>
> I don't see why -- the IO ports are implemented as parameters, which
> means that you can change them for a given dynamic extent -- one where
> compilation happens, or one where runtime happens.


I think there's been a misunderstanding. My question was:

Q. Are there different (current-input-port), etc., at different phases?

Your answer was:

A. No -- which makes this [I assume current-input-port] a "back-door".


So, there are no different current-input-ports for different phases;
there is only one such parameter shared between all phases; right?

My next question was: since such feature (like current-input-port) is
useful in practice (and is part of the standard), how can I implement
it? For which you said that if I'm trying to do this, them I'm not
solving the problem correctly.

Please confirm or correct my understanding of your position.

Aziz,,,

Abdulaziz Ghuloum

unread,
Nov 3, 2008, 3:53:00 AM11/3/08
to
Eli Barzilay wrote:
> Abdulaziz Ghuloum <aghu...@cee.ess.indiana.edu> writes:
>
> You mean non-generative? If so, then I think that this is the
> relevant bit:
>
> http://docs.plt-scheme.org/guide/define-struct.html#(tech._prefab)

I don't want prefabbed solutions that cannot be implemented in the
language. I was asking about how I, as an implementor, would have
implemented them had I been forced to implement separate instantiation
at the same time.

Let me repeat the question again:

>> How would there be a globally unique mapping from uids to record
>> type descriptors if all phases are separate?

(and had Matthew not blessed the PLT users with prefab structs; which
only came very recently IIRC)

Aziz,,,

Eli Barzilay

unread,
Nov 3, 2008, 3:58:45 AM11/3/08
to
Abdulaziz Ghuloum <aghu...@cee.ess.indiana.edu> writes:

> Eli Barzilay wrote:
>> Abdulaziz Ghuloum <aghu...@cee.ess.indiana.edu> writes:
>>
>>> Eli Barzilay wrote:
>>>
>>>>> 5. Are there different (current-input-port), (current-output-port),
>>>>> (current-error-port),
>>>> No -- which makes this a "back-door" similar to using the
>>>> filesystem.
>>> Okay, but this is a very useful feature that we all use everyday.
>>> But with the phase separation, I cannot implement such facility
>>> (like a current-sdl-window for example).
>>
>> I don't see why -- the IO ports are implemented as parameters, which
>> means that you can change them for a given dynamic extent -- one where
>> compilation happens, or one where runtime happens.
>
>
> I think there's been a misunderstanding. My question was:
>
> Q. Are there different (current-input-port), etc., at different
> phases?
>
> Your answer was:
>
> A. No -- which makes this [I assume current-input-port] a
> "back-door".
>
>
> So, there are no different current-input-ports for different phases;
> there is only one such parameter shared between all phases; right?

Yes -- only one parameter. (And only one input port.)


> My next question was: since such feature (like current-input-port) is
> useful in practice (and is part of the standard), how can I implement
> it? For which you said that if I'm trying to do this, them I'm not
> solving the problem correctly.

Looks like the misunderstanding is: you're asking how to implement
*the* `current-input-port' parameter as an *implementor*, right? If
so, then yes, you need to do so in the core (C or whatever you use for
the core). It cannot be done inside the language:

> (module A scheme (provide x) (define x (make-parameter #f)))
> (require 'A (for-syntax 'A))
> (define-syntax (foo stx) #`'#,x)
> (eq? x (foo))
#f

Eli Barzilay

unread,
Nov 3, 2008, 4:02:45 AM11/3/08
to
Abdulaziz Ghuloum <aghu...@cee.ess.indiana.edu> writes:

> Eli Barzilay wrote:
>> Abdulaziz Ghuloum <aghu...@cee.ess.indiana.edu> writes:
>>
>> You mean non-generative? If so, then I think that this is the
>> relevant bit:
>>
>> http://docs.plt-scheme.org/guide/define-struct.html#(tech._prefab)
>
> I don't want prefabbed solutions that cannot be implemented in the
> language. I was asking about how I, as an implementor, would have
> implemented them had I been forced to implement separate
> instantiation at the same time.

[This looks like the same misunderstanding as the previous post.]

Prefabs are generally similar to some simple representation like a
vector with a special tag value that is used to identify them. (And a
prefab structure "definition" is only used to materialize the related
functions, not to create the type.)

They do need to be added as a new primitive to the language if you
want them to be a distinct type.

Abdulaziz Ghuloum

unread,
Nov 3, 2008, 4:05:26 AM11/3/08
to
Eli Barzilay wrote:

>> 7. In what phases are libraries obtained from (environment ---)
>> instantiated? Are they the same or different from the set of
>> libraries instantiated for run, expand, meta-2, etc.? Would
>> calling (environment '(foo)) twice cause two different instances
>> or foo, or just one? What about calling (environment '(foo))
>> from different phases? What about calling (environment '(foo))
>> from within eval itself? Does recursive calls to eval and
>> environment cause instantiation of arbitrary number of instances?
>
> I think that the namespace documentation is relevant here.

No it's not relevant since it did not come as part of the draft or
the final standard of Scheme. You see, PLT may have all the nuts
and bolts for dealing with phasing issues. However, the stuff that
was proposed for R6RS's phase semantics (like separate instantiation)
is not sufficient for implementing even the features that are found
in R6RS itself. This is one reason why no implementation (other than
mzscheme) implements separate instantiation of libraries/modules for
different phases. And this is why we ended up with the compromise
position on semantics that we're in now.

Aziz,,,

Eli Barzilay

unread,
Nov 3, 2008, 4:17:51 AM11/3/08
to
Abdulaziz Ghuloum <aghu...@cee.ess.indiana.edu> writes:

> Eli Barzilay wrote:
>
>>> 7. In what phases are libraries obtained from (environment ---)
>>> instantiated? Are they the same or different from the set of
>>> libraries instantiated for run, expand, meta-2, etc.? Would
>>> calling (environment '(foo)) twice cause two different instances
>>> or foo, or just one? What about calling (environment '(foo))
>>> from different phases? What about calling (environment '(foo))
>>> from within eval itself? Does recursive calls to eval and
>>> environment cause instantiation of arbitrary number of instances?
>>
>> I think that the namespace documentation is relevant here.
>
> No it's not relevant since it did not come as part of the draft or
> the final standard of Scheme.

Clarification: I suspect that environments translate to namespaces in
the PLT implementation of r6rs. I cannot say much more because I'm
not the one who did that implementation.


> You see, PLT may have all the nuts and bolts for dealing with
> phasing issues. However, the stuff that was proposed for R6RS's
> phase semantics (like separate instantiation) is not sufficient for
> implementing even the features that are found in R6RS itself. This
> is one reason why no implementation (other than mzscheme) implements
> separate instantiation of libraries/modules for different phases.
> And this is why we ended up with the compromise position on
> semantics that we're in now.

I don't think that this is the reason for the compromise -- if it was
agreed to include phase separation (and/or multiple instantiations) in
r6rs, then any required nuts and bolts could be added. (Notes: I
don't know exactly which nuts and bolts these would be; and this is,
of course, pure speculation on my side -- I have no knowledge of the
process beyond what is public (and likely much less than what you know
about it).)

Derick Eddington

unread,
Nov 3, 2008, 4:35:38 AM11/3/08
to
On Nov 2, 9:51 pm, Abdulaziz Ghuloum <aghul...@cee.ess.indiana.edu>
wrote:
> The question to you, Derick, since you've written and
> ported so many R6RS libraries so far (maybe more than the rest of us
> combined) is: How many times did you need to restrict bindings to
> one level or another?

When I've needed bindings for "expand" level, they're often required
only at "expand", and since I have to make the (for --- level ...), in
those cases I make it for only "expand". The stuff I've been doing
doesn't involve complicated phase / level issues. I've been focusing
on "grunt" work I need to do first.


[d@eep:~/zone/scheme/xitomatl]-> irregex-tool single '\(\s*for\s+\(.+?
\)(?:\s+\w+)+?\)' .
("./IU-match.sls"
("(for (rnrs) run expand)")
)
("./exceptions.sls"
("(for (only (xitomatl macro-utils) with-syntax* gen-temp) expand)")
)
("./fuego.sls"
("(for (only (xitomatl macro-utils) with-syntax* gen-temp) expand)")
)
("./generics.sls"
("(for (only (xitomatl macro-utils) identifier-append) expand)")
)
("./include.sls"
("(for (xitomatl include compat) expand)")
("(for (xitomatl file-system paths) expand)")
("(for (xitomatl conditions) expand)")
)
("./keywords.sls"
("(for (only (xitomatl macro-utils) \n with-syntax* gen-
temp identifier?/name=?)\n expand)")
)
("./match.sls"
("(for (only (xitomatl macro-utils)\n identifier?/
name=? name=? unique-ids?/raise)\n expand)")
("(for (only (xitomatl indexes)\n enumerate)")
("(for (only (xitomatl predicates)\n exact-non-negative-
integer? exact-positive-integer?)\n expand)")
)
("./rnrs-profiled.sls"
("(for (rnrs eval) expand)")
("(for (only (xitomatl macro-utils) identifier-append) expand)")
("(for (only (xitomatl r6rs-bindings utils) variables-of) expand)")
)
("./sxml-match-1-0.sls"
("(for (xitomatl sxml-match void) run expand)")
)
("./IU-match/extras.sls"
("(for (xitomatl IU-match macro-helpers) expand)")
)
("./define/define-values.sls"
("(for (only (xitomatl macro-utils) formals-ok?) expand)")
)
("./define/extras.sls"
("(for (only (xitomatl macro-utils) formals-ok? syntax->list)
expand)")
)
("./srfi/cond-expand.sls"
("(for (xitomatl srfi private registry) expand)")
)
("./srfi/private/include-resolve.sls"
("(for (xitomatl srfi private include-resolve compat) expand)")
)
[d@eep:~/zone/scheme/xitomatl]->


> And have you ever been bitten by Ikarus's
> implicit phasing semantics? (other than when trying to run your
> code under plt and realizing that it didn't work of course)

No.

--
: Derick
----------------------------------------------------------------

Abdulaziz Ghuloum

unread,
Nov 3, 2008, 4:38:23 AM11/3/08
to
Eli Barzilay wrote:

> Looks like the misunderstanding is: you're asking how to implement
> *the* `current-input-port' parameter as an *implementor*, right? If
> so, then yes, you need to do so in the core (C or whatever you use for
> the core). It cannot be done inside the language:
>
> > (module A scheme (provide x) (define x (make-parameter #f)))
> > (require 'A (for-syntax 'A))
> > (define-syntax (foo stx) #`'#,x)
> > (eq? x (foo))
> #f

Thanks for the clarification Eli. The reason for the misunderstanding
was due to the difference in the value/burden each of us puts on the
implementor. In my view, there is no difference between an implementor
of Scheme system and a user of the system. (1) I, as an implementor,
would never inflict on my users some semantics, which I myself do not
follow. I don't advocate some semantics for Scheme, how its libraries
should behave, when they're instantiated, etc., only to escape to
somewhere outside of the language (like C) to implement such semantics.
(2) There are people who use Ikarus to implement their own languages,
compilers, interpreters, etc., and it would be a shame if they are
considered less-privileged than I am when it comes to implementing
some of these useful features.

It is unfortunate that something as useful as global parameters cannot
be done in the language of MzScheme.

I think your answer pretty much sums it up. Thanks.

Aziz,,,

Michele Simionato

unread,
Nov 3, 2008, 4:46:47 AM11/3/08
to
On Nov 3, 7:57 am, Abdulaziz Ghuloum <aghul...@cee.ess.indiana.edu>
wrote:

> Basically, your syntax-match macro is trying to phase-shift itself
> into the next level!  I have been trying for more than a year to
> find a real life (not a contrived) example of a macro that actually
> expands to a use of itself at the next level, and failed.  And now
> you come and throw it at my lap.  Thanks!

Eh, eh, it reminds me the reaction of Guido when I wrote the C3
paper ;)
I am happy if my module was of some help for you.

Writing it was not trivial, but porting it is much worse, it looks
like I opened a can of worms, exposing all the dark corners of Scheme.
I have just filed another bug report for Ypsilon, which fails with
syntax-expand too, but with a different error. I have not tried to run
sweet-macros code on Larceny and on Mosh, but I would be very
surprised if it worked out of the box. Help is appreciated, of course.

Michele Simionato

Eli Barzilay

unread,
Nov 3, 2008, 4:51:27 AM11/3/08
to
Abdulaziz Ghuloum <aghu...@cee.ess.indiana.edu> writes:

> Eli Barzilay wrote:
>
>> Looks like the misunderstanding is: you're asking how to implement
>> *the* `current-input-port' parameter as an *implementor*, right?
>> If so, then yes, you need to do so in the core (C or whatever you
>> use for the core). It cannot be done inside the language:
>>
>> > (module A scheme (provide x) (define x (make-parameter #f)))
>> > (require 'A (for-syntax 'A))
>> > (define-syntax (foo stx) #`'#,x)
>> > (eq? x (foo))
>> #f
>
> Thanks for the clarification Eli. The reason for the
> misunderstanding was due to the difference in the value/burden each
> of us puts on the implementor. In my view, there is no difference
> between an implementor of Scheme system and a user of the system.

[Off-topic: the holy grail of a practical language that is implemented
completely in itself is something that I have never seen. And if you
look at my thesis you'll see that I spent considerable efforts in the
reflection neighborhood.]


> (1) I, as an implementor, would never inflict on my users some
> semantics, which I myself do not follow. I don't advocate some
> semantics for Scheme, how its libraries should behave, when they're
> instantiated, etc., only to escape to somewhere outside of the
> language (like C) to implement such semantics.

The case of the IO ports is a good example here: you *do* have
different rules than your users -- you're the one who makes the
`ikarus' executable, so you're the one who sees the true OS IO ports
and you're the one who's in charge of translating them to Scheme level
values. (Obviously, your users can do the same thing using a
reflective tool (an ffi, usually) -- but that works out in a similar
way in PLT.)


> (2) There are people who use Ikarus to implement their own languages,
> compilers, interpreters, etc., and it would be a shame if they are
> considered less-privileged than I am when it comes to implementing
> some of these useful features.

Naturally, it is possible to implement such languages in PLT too (but
that's close to a TM-nonargument). However, the above still holds --
the IO ports are an external resource and as long as the language in
question is implemented in mzscheme/ikarus, the respective executable
is where that is mapped to a Scheme value.

leppie

unread,
Nov 3, 2008, 4:53:55 AM11/3/08
to
On Nov 3, 11:46 am, Michele Simionato <michele.simion...@gmail.com>
wrote:
> ... I have not tried to run

> sweet-macros code on Larceny and on Mosh, but I would be very
> surprised if it worked out of the box. Help is appreciated, of course.

Mosh uses the current psyntax from Ikarus (or IronScheme, not sure
which was used), hence it will be the same. Ditto for IronScheme.

Cheers

leppie

Michele Simionato

unread,
Nov 3, 2008, 5:11:06 AM11/3/08
to

Chicken too uses psyntax and it works for interpreted code, but I have
not tried to make an egg and I am not sure it will work in compiled
code. Knowledgeable people are invited to try starting from this code:
http://www.phyast.pitt.edu/~micheles/scheme/sweet-macros.scm

Abdulaziz Ghuloum

unread,
Nov 3, 2008, 5:21:18 AM11/3/08
to
Eli Barzilay wrote:

> [Off-topic: the holy grail of a practical language that is implemented
> completely in itself is something that I have never seen. And if you
> look at my thesis you'll see that I spent considerable efforts in the
> reflection neighborhood.]

[off-topic still:
BTW, while Ikarus Scheme (the implementation) is implemented in Ikarus
Scheme (the language), the compiler and run time systems make no use of
reflection whatsoever for bootstrapping. The ikarus compiler used for
bootstrapping is just like any ordinary user program, and it would not
be able to reflect on its environment to tell the difference in whether
it was running interpreted, compiled, within ikarus, or outside of it.
I don't know about holy grails, but it's pretty neat.]

Aziz,,,

Derick Eddington

unread,
Nov 3, 2008, 5:24:03 AM11/3/08
to
On Nov 2, 11:02 pm, Eli Barzilay <e...@barzilay.org> wrote:
> > Eli (or anyone who knows), would you describe why multiple
> > instantiation of libraries is necessary or "the right way" for what
> > PLT does with mutable library/ module state?
>
> [I don't know what description you expect. Hopefully the above helps
> clarifying.]

Yes it has, along with your later comments. Thanks.

What Will Clinger said:

On Nov 2, 9:56 pm, William D Clinger <cesur...@yahoo.com> wrote:
> With Larceny's semantics, you
> can obtain the effect of the PLT semantics by
> duplicating libraries. With the PLT semantics,
> however, you cannot obtain the effect of Larceny's
> semantics.
>
> That means Larceny's semantics is more expressive
> than the PLT semantics. That doesn't mean Larceny's
> semantics is "the right way", but it does prove that
> the PLT semantics is not the only way to obtain the
> behavior Eli prefers.
>
> In short: Multiple instantiation of libraries is
> unnecessary, even for Eli's examples.

suggests to me we should have both and make everybody happy (about
library instantiation). If we can adequately/expressively say when/
how we want duplicated libraries so they can have fresh state (and
whatever other ways multiple instances can be used) and also have
single-instantiation, and if this can be done portably, we can all
benefit from having both options. But I don't understand the deeper
implications, so maybe it's not feasible or a good idea to have both
portably..?

--
: Derick
----------------------------------------------------------------

Abdulaziz Ghuloum

unread,
Nov 3, 2008, 5:34:32 AM11/3/08
to
Derick Eddington wrote:

> [...] But I don't understand the deeper implications, so maybe


> it's not feasible or a good idea to have both portably..?

Without much thought I'd say that for anything I implement, I'd
rather have one and exactly one of such thing. Combinations of
related, close, but slightly different features is my #1 enemy.
E.g., I still haven't won at consolidating Ikarus's structs and
R6RS's records, and it's a pain every time I look at it, even
though both work fine according to their specs.

Aziz,,,

Eli Barzilay

unread,
Nov 3, 2008, 5:35:26 AM11/3/08
to
Abdulaziz Ghuloum <aghu...@cee.ess.indiana.edu> writes:

[Even more off-topic: That's a pretty common story: you choose where
to draw the line and get a reflective implementation from there and
up. I consider as holy grail something that would be reflective to an
extreme (I can't say completely reflective, since that's either vague
or false). For example, an ultimate trick to pull is -- make a
theorem prover that can run a proof of its own correctness and extract
itself from that proof. But that involves fighting all kinds of
logical demons (many with non-ascii characters in their names).]

William D Clinger

unread,
Nov 3, 2008, 7:56:51 AM11/3/08
to
Eli quoting Aziz:

> > You see, PLT may have all the nuts and bolts for dealing with
> > phasing issues. However, the stuff that was proposed for R6RS's
> > phase semantics (like separate instantiation) is not sufficient for
> > implementing even the features that are found in R6RS itself. This
> > is one reason why no implementation (other than mzscheme) implements
> > separate instantiation of libraries/modules for different phases.
> > And this is why we ended up with the compromise position on
> > semantics that we're in now.
>
> I don't think that this is the reason for the compromise....

The R6RS editors were aware that the multiple instantiation
semantics would not have been adequate to implement the R6RS
itself. That was definitely one of the reasons that some
editors insisted upon allowing single instantiation.

Will

William D Clinger

unread,
Nov 3, 2008, 8:11:32 AM11/3/08
to
Tom Gordon wrote:
> That was a very long way to concede Aziz's point: There was no
> standard for REPLs in R5RS and there still is no standard for REPLs in
> R6RS.

Your statement is misleading. In Aziz's defense, he
said no such thing.

The R5RS defined a standard semantics for REPLs. The
R6RS did not.

Neither the R5RS nor the R6RS requires a REPL, just as
neither requires separate compilation. The R6RS semantics
was designed to support separate compilation, however,
just as the R5RS semantics was designed to support REPLs.

That analogy is flawed because the R5RS semantics also
allows separate compilation, but the R6RS semantics does
not allow REPLs.

Although neither the R5RS semantics nor the R6RS semantics
is categorical, that does not mean the R5RS and R6RS fail
to define a semantics. In particular, it does not mean
there is no semantics for REPLs in the R5RS, and it does
not mean there is no semantics for separate compilation
in the R6RS.

Will

It is loading more messages.
0 new messages