Egil Möller:
>  I was thinking about the {}-infix notation and implementation, and realized 
> a rather sad side-effect - the actual parse-tree, what is fed to eval, does 
> not resemble the input any longer, as it does for all other syntax sugar 
> (quoting and so on).
> My suggestion is to simplify the reader-macro, so that it only rewrites {1 * 
> 2 + 4 * {5 + 6}} into (nfx 1 * 2 + 4 (nfx 5 + 6)) and do the rest with an 
> ordinary macro, nfx.

I also prefer seeing the actual parse-tree, but I have the exact opposite 
solution: Keep the rules, and I plan to _avoid_ (in most cases) writing code 
that invokes "nfx".  In other words, I plan to do this:
{3 + {4 * 5}}
so that it will auto-map into (+ 3 (* 4 5)), and avoid doing this:
{3 + 4 * 5}

This means that the actual parse tree DOES represent the input - every new list 
is marked with either (...) or {...}.  The only thing that's unusual is the 
swapping of the argument order.... but hey, that's the WHOLE POINT of having 
infix, to have the infix operator NOT in the first position.  I've done some 
experimentation and find it's actually quite easy to get used to.

There's also a pragmatic reason: if the expression is hidden inside an 
execution time/compile time macro and/or special form, the expression _WILL_ be 
correct.  A reader can do that... a macro like "nfx" cannot.

I actually originally planned to make infix processing produce an ERROR in the 
case where it produces (nfx ...).  But Gloria's comments made me realize that 
at little cost I could do much better - instead of an error, hand it off to a 
macro and let the user decide how to handle it.  It isn't any more complex to 
implement the reader, and it's much more flexible.

> It would be easy to add a printing hook that rewrites anything (nfx ...) into 
> {...}, just like it works for quotes.

True, but I think it's reasonable that a _printing_ hook have some "smarts" 
that try to make it look pretty. E.G., if a function name is all-punctuation, 
"and", "or", or "xor", use the {...} format.  So a printing hook can see (+ 4 
5) and print {4 + 5} just as easily.  The printing hook doesn't need to print 
everything EXACTLY how it was input; (quote x) is printed as 'x  by many 
printers.  But I think it needs to be very clear and unambiguous.

I think I'd want (nfx ....) to be printed as (nfx ....) - or better yet, 
nfx(....).  If it's an argument to a macro, that additional (nfx ....) might 
make a key difference, and I DEFINITELY don't want to create debugging problems 
by hiding that information.  Again, I plan to use the "simple infix" (swapping) 
as the NORMAL use of {...}, and only rarely use (nfx ....).

> One way to handle operator precedence would be to call a special function for 
> each pair of used operators: {1 * 2 + 4 * {5 + 6}} (precedence_*_+ 1 2 4) -> 
> * (precedence_+_* 2 4 11) -> *

You don't want to do it QUITE that way.  In any case, precedence-handling is 
old stuff, techniques are well-known.  You can give each operator a precedence 
value, or state orderings for pairs.

But I think that precedence-handling is a suboptimal idea in a reader.  It's 
not that it can't be done... it CAN be done easily enough, you just configure a 
table.  The problem is that what an expression means depends on the particular 
state of this table.  You have to be REAL careful of the exact state of this 
table; an expression's interpretation could DIFFER after each change.  When 
merging people's code this could be especially nasty.

If you're dealing with data that express different sublanguages (this is my 
program, this over there is input that is a special-purpose language, etc.), 
then it gets worse - they probably have different operators, with possibly 
different precedence.  Uh oh. And what's more, there are endless ways of 
handling precedence, no one can seem to agree.  It's also easy to implement it 
incorrectly.

I think a basic, SIMPLE rule for reading MOST infix expressions - and then 
handling off to a macro for more complex cases - is the better approach.  I 
wrote the Common Lisp implementation of curly braces in little time, and I 
believe it's rock-solid.  After all, it's quite simple!  Being _certain_ that 
you know what the code will do has its own advantages. :-)

--- David A. Wheeler

Reply via email to