guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: local-eval on syntax-local-binding, bound-identifiers


From: Andy Wingo
Subject: Re: local-eval on syntax-local-binding, bound-identifiers
Date: Tue, 17 Jan 2012 00:27:07 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.3 (gnu/linux)

Hi Mark,

On Mon 16 Jan 2012 21:36, Mark H Weaver <address@hidden> writes:

> Thanks again for working on this.

And thank you again for all your work, and patience with my
pigheadedness.

> if you insist in this foolish quest to banish `the-environment' to
> sleep in the shed as a second-class citizen, I cannot stop you :)

TBH I think this is the best thing we can do for local-eval.  We
preserve flexibility for local-eval, make other experiments possible,
and the local-eval implementation is a bit more perspicacious, as the
scoping is more lexical (in the same file, even).

I know there's a smilie in your statement, but really, it's not just
local-eval:  there's loads more that should be broken out into modules
over time, somehow :)  Think of it as building a hippie commune of
functionality, instead of making everyone live in the same house :)
(OK, that's stretching it a bit, but perhaps it is partially apt?)

Now, specific commentary.

> How about something like (bound-identifiers #'here)?

scheme@(guile-user)> (bound-identifiers #'here)
$5 = ()

scheme@(guile-user)> (let ((x 10)) (bound-identifiers #'here))
$6 = (#(syntax-object x ((#f top) shift #(ribcage #(x) #((top)) #("i176"))) 
(hygiene guile-user)))

What should the answer be in this case?  Would you expect `x' in the
list?  Certainly for the-environment you would.  But here:

scheme@(guile-user)> (define-syntax bound-here
                       (lambda (x)
                         (with-syntax (((id ...)
                                        (map (lambda (id) (datum->syntax x id))
                                             (bound-identifiers #'here))))
                           #'(list 'id ...))))
scheme@(guile-user)> bound-here
$7 = (#(syntax-object x ((#f top) shift #(ribcage #(x) #((top)) #("i192"))) 
(hygiene guile-user)))
scheme@(guile-user)> (let ((y 10)) bound-here)
$8 = (#(syntax-object x ((#f top) shift #(ribcage #(x) #((top)) #("i192"))) 
(hygiene guile-user)))

So, it seems to be sensible.

Now, what to do with these identifiers: you if you introduce one into
another macro, the mark will indeed be stripped.  I'm not sure what else
you can do with a syntax-object, actually!  Pass it directly to eval or
compile, I guess, and in that case we do lose, as the anti-mark isn't
stripped.  But that's the case for other syntax objects captured in a
syntax transformer, as well.

Should we anti-mark only within the dynamic extent of a transformer, I
wonder?

> As I've already said, I don't think `bound-identifiers' will be useful
> in a full implementation of `local-eval', so once we move to that
> improved implementation, `bound-identifiers' will be left around as an
> orphan: a primitive of dubious value, introduced specifically to
> implement something that it turned out to be insufficient for.

Hummmmm.  Definitely something to think about.

What if instead we implemented closure serialization somehow?  Then we
would handle procedural macros too, and bound-identifiers would still be
sufficient.

Maybe that idea is a little too crazy.

If we have to lexical contours associated with bindings, recursive is
only one bit: you probably also need letrec vs letrec*.

>> To be perfectly honest, this stuff is very confusing to me, but I think
>> I can see how this can happen, yes.
>>
>> I do think that it's important to fix this bug at some point, but IMO it
>> is not a blocker for local-eval, much less 2.0.4.
>
> I strongly disagree.  Your implementation will clearly be buggy without
> a proper solution to the collision of gensyms (labels and marks, at
> least).  I don't know about you, but personally I prefer rock-solid code
> with clearly documented limitations (that almost no one is likely to hit
> anyway) to buggy code.
>
> If you don't want to deal with the gensym problem for 2.0.4, there's an
> easy solution.  Simply strip the wraps for now (as is done by my patch),
> and everything will robust as long as we don't capture local syntax.

Thinking about it a little more, labels are a non-issue.  All they need
to be is unique in the sense of eq?.  Labels are strings.  If they are
loaded in separate compilation units, they will be unique, no matter
what their contents.

Labels are more important than marks, also, for the correctness of the
algorithm.  A mark collision is only an issue if there is also a
symbolic collision.  Label collision could alias completely unrelated
bindings.

Anyway, I would rather serialize bad marks than no marks.  That's my
personal opinion ;-) But if you think this is a huge issue, let's fix
the marks to be more unique, no?

Note that there is a well-known optimization that you don't actually
need to generate the characters corresponding to a gensym until they are
needed.  It might serve your purposes.

OK, I'm getting very sleepy now :)  Let me know your thoughts.  It would
be great if all of this could land before Sunday.  Though the cricket
folk say "pace is nothing without guile", Guile is nothing without a
good development pace ;-)

Cheers,

Andy
-- 
http://wingolog.org/



reply via email to

[Prev in Thread] Current Thread [Next in Thread]