My approach to readability combines 3 basic approaches, and I've recently 
realized that they can be described and layered separately... and I plan to 
describe them that way.  I've also implemented layers #1 and #2.  I'd love to 
hear feedback on all this, so here we go...

Basically, I think my approaches can be grouped into 3 alternatives, which 
layer on each other:
1. Curly infix.  Expressions in {...} become infix (always), so {3 eq? 4} 
becomes (eq? 3 4).  This ONLY provides infix (and obviously there are other 
ways to do this too).  But since it uses the unused {...}, it's perfectly 
backwards-compatible... you could add this to any existing reader without 
harming anything else.

2. Modern-expressions, aka mod-expressions.  This adds "term prefixing" - if a 
symbol or list is followed (without whitespace) by (), [], or {}, then it has a 
different meaning.  In addition, unprefixed [..] also creates lists.  So f(x y) 
becomes (f x y), f{x + y} becomes (f (+ x y)), etc.  This is generally 
backwards-compatible with nicely-formatted code, but it IS a change, and badly 
formatted code like (A(B)) would be interpreted as ((A B)) instead of (A (B)).

3. Sweet-expressions.  This takes modern-expressions and adds indentation 
(I-expressions).

I have posted a production-ready implementation of "curly infix" for Common 
Lisp; Common Lisp's macro characters make it easy to support them without much 
fuss.

This morning I've posted on the svn server a first-cut implementation of 
"modern-expressions" in Scheme, as "modern.scm".   It's still a little wet 
behind the ears. but it passes 81 test cases... so it should be reasonably 
robust.

Unfortunately, to implement modern-expressions in most Scheme implementations, 
you have to completely re-implement Scheme's "read" function, because most 
Scheme readers don't consider [,],{, or } as delimiters.  That's too bad; 
implementing mod-expressions actually doesn't take much code (most of my 
implementation is just a re-implementation of "read").  Still, "read" is not 
THAT hard to re-implement, so I've done so. A disadvantage is that you can't 
use whatever extensions of the reader exist while using modern-expressions (aka 
mod-expressions).  In the long term, I'd like these readers built into the 
implementation, but this is MORE than good enough for experimentation and 
eventually real work.

I believe that once we have a properly-working I-expression reader, it should 
be able to directly build on modern-expressions, automatically creating a 
sweet-expression 0.2 reader. Yum.

I've now done a lot of experimentation to create test cases, etc. Based on that 
experience, I now have the following opinions:
* (...) should NOT normally disable modern/sweet-expressions; at best, an 
optional mode could implement that.  Although it's a nifty fop to 
backwards-compatibility, it's absurdly easy to use (...) for a list when you 
did NOT intend to disable mod-expressions.  What's worse, it's really hard to 
find which parens actually did the disabling.  It's much better to have both () 
and [] just mean "make a list" - this is consistent with much practice (Scheme 
R6RS even enshrines this).
* Prefixing of (), [], and {} should ONLY be acceptable if the prefix is a 
symbol or list; otherwise, ignore it.  It's exceedingly unlikely that someone 
who wrote 9(i) meant (9 i).

Thoughts? Comments?

--- David A. Wheeler 

Reply via email to