Hi Mark, On Mon 16 Jan 2012 21:36, Mark H Weaver <m...@netris.org> 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/