Beni Cherniavsky-Paskin:
> Summary: I only buy the first of the use cases; I think this construct will
> be rarely used and want the sematics to be as simple as possible; I propose
> some alternative ideas below.

First of all, thanks SO MUCH for posting!! I'm a big believer in feedback, so I 
really appreciate your time.

I agree that the first use case (multi-line libraries) is more important, which 
is why I put it first.
I do think the other use case is relevant, though, especially if we can resolve 
both at once.

I completely agree that the final semantics need to be "as simple as possible". 
 In general, I try to do a lot of experimentation and out-of-the-box thinking 
before deciding on something specific, so please don't assume that some more 
complicated draft structure is the "final word".

> If we separate the 2 issues, I feel the no-blank-lines is the more
> problematic of them.  In Python, I'm fine with most of my defs being
> indented because they're class methods, but couldn't live without new lines.
> Do you agree?

I don't *exactly* agree, though you may be missing an element of 
sweet-expressions that makes end-on-blank-lines work.  But first, my priorities.

My current view is that the more important requirement is that the REPL and 
file format need to be exactly the *same* in a Lisp-based system. In Python you 
often cannot cut-and-paste from files into the command line ("REPL"), because 
Python files and the REPL have different blank-line semantics.  (Technically, 
the Python spec only covers files, but that's a useless nuance.)  That's 
actually a problem in Python today, and annoys me sometimes.  In a Lisp such a 
difference would be crazy, because Lisps are programmable programming languages 
where experimentation is common.

Now for blank lines.  Blank lines ending an expression actually isn't bad, even 
in a larger program, because of the rule that comment-only lines (possibly 
indented) are completely ignored, and do NOT end an expression.  I agree that 
without that rule it'd be hideous to use, but using comment-only lines to 
vertically separate material actually works very cleanly.

It's not insane to use some marker to mean "end of expression", several 
languages do that.  Indeed, sweet-expressions could be modified to that easily 
enough.  But then users have to remember to do that after every expression.  If 
REPL use is rare, that'd be fine.  But I expect lots of people to use the REPL, 
often, and I want the REPL to be very pleasant to use.  It's hard to beat 
"enter a blank line to evaluate".

But this approach does have a downside with long library declarations (and 
similar structures). In these cases, the endless indentation *and* the blank 
lines ending expressions both start to get annoying.  Thus, the <* ... *> 

> > Now let's look at the second use case.
> > The sweet-expression notation cleanly handles cases where let-expression
> > variables have complex values (e.g., using \\), but for simple cases
> > (1-2 variables having short initial values) ...

> I completely don't get it.
> What's wrong about ((x 5) (y 7)) or (x{5} y{7}),
> and why is <* x 5 *> or <* (x 5) *)> any better?
> When compressing nested lists on one line, parens are the - clearest way to
> represent structure.
> Specifically, I dislike the usage where <* x y *> implies a double list by
> restarting the multiple-items-on-a-"line" rule.  While I see the consistent
> logic of this semantics, it's IMHO way too hard to scan this visually as a
> double list - a problem ((...)) doesn't have.

Well, the current notation is obviously not a disaster, since we've written 
programs without it.  But when the variables involve modest amounts of 
calculation, it gets harder to see what you're doing than I'd prefer, because 
it's easy to suddenly require more paren-nesting than is typical in other 


let ((x cos(f(c))))
! dostuff x

let <* x cos(f(c)) *>
! dostuff x

let <* x $ cos $ f c *>
! dostuff x

In one-variable lets, a common mistake is to forget to embed the variable in 
double-parens.  Since the parens are also usually used for the expression 
calculation, it can be easy to miss.  Making it possible to visually 
distinguish the outer "parens" that create the variable list, from the internal 
parens used for the expression, makes it clearer which parens are more 
structural vs. the ones involved in the variable calculation.   That, in turn, 
makes it easier to notice the omission of doubled parens for one variable.

> As I see it, we need some solution for the very-long-form problem, while
> one-liner-let is a solved problem.
> If restricting <* .. *> to EOL - or even requiring them to stand alone on a
> line - makes for a simpler spec, I'd much rather see that rather than fine
> tuning the inline semantics.

An excellent point.  Yes, I agree that simplicity (of spec and implementation) 
is really important.  The older experimental rulesets for <* ... *> were 
probably a good case-in-point of complications that, if we *had* to do them, 
were a good argument against them.

As it turns out, the new ruleset for <*...*> that I just posted is quite 
simple, and it basically only requires one extra line in the spec to handle the 
on-the-same-line case.

> I agree that "two-liner-let" is not a solved problem.  We can either cram
> it on 1 line, or nicely spread on 1+N lines using \\, but not on N lines.

It turns out the new ruleset handles this case as a byproduct, and doesn't 
require any new code or productions to make it work.  Which in my mind is 
evidence that it's the right direction... ideally a grammar should have a few 
powerful productions that keep getting reused.

> IMO this goes deeper than just let but I don't think abusing <*..*> is an 
> improvement.

Fair enough.

>  I'll try to post thoughts on this in the z language thread.


> IMHO, it's very ugly that "example grid ..." are indented when the body of
> the library isn't.  Indentation should be (at least) non-decreasing!

Hmm, I view this as a *solution*.  There's only so much horizontal and vertical 
space.  If nearly the entire file is indented to several levels, that means 
there's less (horizontal) room to express actual content.

I completely agree that indentation should *NORMALLY* be non-decreasing, but 
the point of this structure is to "restart" indentation so you're not stuck 
writing all content on the right edge.

> If I were to use a construct like this, I'd either have "define ..."
> indented deeper (only using <*..*> for blank line freedom), or flatten the
> containing lists at indent zero (on the theory it should actually be
> negative):
> <*
> define-library
> example grid
> export make rows cols ref each rename(put! set!)
> import scheme(base)
> <*
> begin
> define make(n m)
>   let (grid(make-vector(n)))
> ...
> *>
> *>

I wouldn't format the first define-library...import that way, but that's 
certainly consistent with the current draft semantics.  Perhaps more 
importantly, the second "<*" is definitely the way I'd expect to see it used.

> I'm deliberately restricting <* to the head of the list.  I see it as an
> esoteric construct, and this is the simplest least-surprise version.

Okay.  I actually agree with you that multi-line "<*" should be used relatively 
sparingly, as it's a powerful tool that can confuse if misused.  But we're 
noticing its LACK as we write bigger programs, so that's why we're addressing 

> Which is also a weakness IMHO.  Visually, < and > don't feel like a list
> start/end, at least not to lisp eyes.  ([{ / }]) have a history as list
> delimiters, < / > not so much.

Fair enough.  But no other character pairs, other than <..>, are available in 
least-common-denominator ASCII.  Also, while I think <*...*> is important, I do 
not think many lines of code will directly *use* these symbols (especially in 
the multi-line case).  So even if I COULD find another character pair (and ), I 
don't think I would want to use up valuable single-character pairs on this 
functionality; it's perfectly fine to use multi-character markers.

That said, if there are multi-character symbols that you think would better 
"feel" like list start/end, let us know!  I thought about using "<<" and ">>", 
which look like guillemets and probably "feel" more like list start/end.  But 
Scheme systems like scsh already use these symbols (e.g., use >> for 

Suggestions?  The actual marker sequence would be trivial to change now... and 
impractical to change later.

The rest of your post has interesting ideas I need to think about, but I have 
to run right now.

--- David A. Wheeler

Master Java SE, Java EE, Eclipse, Spring, Hibernate, JavaScript, jQuery
and much more. Keep your Java skills current with LearnJavaNow -
200+ hours of step-by-step video tutorials by Java experts.
SALE $49.99 this month only -- learn more at: 
Readable-discuss mailing list

Reply via email to