Re: [Readable-discuss] RESTART <*..*>

2013-01-18 Thread David A. Wheeler
Alan Manuel Gloria noted that with:
> (cond
>   ((< x -1) (* x x))
>   ((> x 1) (* x x))
>   ((< x 0) (sqrt (abs x)))
>   (else (sqrt x)))
> 
> ..without $, we'd have to use:
> 
> cond
>   (< x -1)
>   * x x
>   (> x 1)
>   * x x
>   (< x 0)
>   sqrt (abs x)
>   else
>   sqrt x
> 
> ...with $:
> 
> cond
>   (< x -1) $ * x x
>   (> x 1) $   * x x
>   (< x 0) $ sqrt $ abs x
>   else $ sqrt x

To be fair,  I would write this particular case using parens and infix, as:
cond
! {x < -1} {x * x}
! {x > 1}  {x * x}
! {x < 0}  sqrt(abs(x))
! else   sqrt(x)

> but if you're using multiple expressions, you should really be using
> indentation anyway.

Fair enough.

> (admittedly, you can also just retain the parentheses, but every
> parenthesis cuts the power of t-expressions, because parentheses
> disables stuff.)

Well, it only disables indentation-processing stuff; you still have infix, 
traditional function application, and n-expression suffixes.

Since this case just uses parens for traditional functional application, and 
it's not deeply nested, I'd do it the other way as I've shown above.  This is 
one of those situations where there are 2 good ways; both are reasonable.  I 
think *EITHER* approach is an improvement over traditional notation.


> I feel "$" is a really good balance of something-weird (con) but
> extremely useful (pro).

I think "$" is *not* really something weird, because it's already in an 
existing language with significant use (Haskell).  Granted, someone who's never 
used Haskell has something new to learn.  But practically all programming 
languages have a large set of infix operations; from that point of view, 
t-expressions have a remarkably tiny set of special "infix" operations.

--- David A. Wheeler

--
Master HTML5, CSS3, ASP.NET, MVC, AJAX, Knockout.js, Web API and
much more. Get web development skills now with LearnDevNow -
350+ hours of step-by-step video tutorials by Microsoft MVPs and experts.
SALE $99.99 this month only -- learn more at:
http://p.sf.net/sfu/learnmore_122812
___
Readable-discuss mailing list
Readable-discuss@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/readable-discuss


Re: [Readable-discuss] RESTART <*..*>

2013-01-17 Thread Alan Manuel Gloria
On 1/17/13, Alan Manuel Gloria  wrote:
> On 1/17/13, David A. Wheeler  wrote:
>>> Personally I'm not (yet?) a big fan of $.
>>
>> Not a problem.  It's grown on me.  Once you have it, you find that
>> patterns
>> where it applies are remarkably common.
>
> (^^)v
>

In support of that, consider the following:

(cond
((< x -1) (* x x))
((> x 1) (* x x))
((< x 0) (sqrt (abs x)))
(else (sqrt x)))

..without $, we'd have to use:

cond
(< x -1)
* x x
(> x 1)
* x x
(< x 0)
sqrt (abs x)
else
sqrt x

...with $:

cond
(< x -1) $ * x x
(> x 1) $   * x x
(< x 0) $ sqrt $ abs x
else $ sqrt x

...which is a lot nearer to the original s-expression.  The only
caveat is that in this form, $ is followed by a *single* expression,
but if you're using multiple expressions, you should really be using
indentation anyway.

(admittedly, you can also just retain the parentheses, but every
parenthesis cuts the power of t-expressions, because parentheses
disables stuff.)

Here's a better example of the intended use of $:

import $ srfi srfi-45
import $ amkg object

; use for debugging
define probe(x)
  print(x)
  x

define lazy-construct(a d)
  lazy $ probe $ let ((rv #f))
set! rv $ object-construct 'cons-cell
object-method-register rv
  'car $ lambda () a
  'set-car! $ lambda (na) $ set! a na
  'cdr $ lambda () d
  'set-cdr! $ lambda (nd) $ set! d nd
rv

--

I feel "$" is a really good balance of something-weird (con) but
extremely useful (pro).

Sincerely,
AmkG

--
Master HTML5, CSS3, ASP.NET, MVC, AJAX, Knockout.js, Web API and
much more. Get web development skills now with LearnDevNow -
350+ hours of step-by-step video tutorials by Microsoft MVPs and experts.
SALE $99.99 this month only -- learn more at:
http://p.sf.net/sfu/learnmore_122812
___
Readable-discuss mailing list
Readable-discuss@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/readable-discuss


Re: [Readable-discuss] RESTART <*..*>

2013-01-16 Thread Alan Manuel Gloria
On 1/17/13, David A. Wheeler  wrote:
> (library
>   (amkg animals (1 0))
>   (export cat (rename (rover dog)))
>   (import (only (amkg pets (1 0)) rover))
>   (define cat (quote meow)))
>
>
> Is that what you expected?

Yes ^^

On 1/17/13, David A. Wheeler  wrote:
>> Personally I'm not (yet?) a big fan of $.
>
> Not a problem.  It's grown on me.  Once you have it, you find that patterns
> where it applies are remarkably common.

(^^)v

>> I'm not against having a way to restart indentation; I just wanted to
>> keep
>> the *option* to not restart it to 0, as a matter of taste.
>> Though in light of empty comments always being available, I'm ok with a
>> construct that always forces indent to 0, if it's simpler.
>
> It's much simpler.  There are some nasty subtleties in *starting* with a
> non-zero indent and trying to make it "mean the obvious" in a Lisp-based
> language; see the draft SRFI for more details if you're curious.  It could
> work in other languages, but in Scheme, it's hard because (1) the "read"
> interface of Scheme is already fixed, and (2) standard Scheme doesn't
> support unlimited unread-char.

*Technically* R5RS and R6RS don't support unread-char, at all.
However, most implementations of Scheme support some kind of
unread-char, and some of them only support a 1-character unread-char.
So we have adopted the limitation of requiring only 1 character
lookahead, which can be done by using (let ((c (read-char port)))
(unread-char c port) c).

>> Another very unbaked idea: perhaps we can take a hint from typography and
>> formats such as reStructuredText, markdown and emacs outline-mode (which
>> all took that hint):
>> Represent most structure using indentation, but some structure above that
>> using several levels of headings.
>
> Not a crazy idea, but that would only deal with the case for multi-line that
> begins on the left edge.  That wouldn't deal with the "small let" case, or
> anything that has some simple prefix.  I know you don't care about "short
> let", but *I* do :-).

An interesting idea IMO.  Hmm.

>> I think like this direction on aesthetic grounds, but I suspect the
>> practical convenience of having some reader macro entering the t-expr
>> parser in the middle of s-expr parsing will prevail.
>
> Yes, that's my thinking too.
>
> --- David A. Wheeler
>
> --
> Master Visual Studio, SharePoint, SQL, ASP.NET, C# 2012, HTML5, CSS,
> MVC, Windows 8 Apps, JavaScript and much more. Keep your skills current
> with LearnDevNow - 3,200 step-by-step video tutorials by Microsoft
> MVPs and experts. ON SALE this month only -- learn more at:
> http://p.sf.net/sfu/learnmore_122712
> ___
> Readable-discuss mailing list
> Readable-discuss@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/readable-discuss
>

--
Master Visual Studio, SharePoint, SQL, ASP.NET, C# 2012, HTML5, CSS,
MVC, Windows 8 Apps, JavaScript and much more. Keep your skills current
with LearnDevNow - 3,200 step-by-step video tutorials by Microsoft
MVPs and experts. ON SALE this month only -- learn more at:
http://p.sf.net/sfu/learnmore_122712
___
Readable-discuss mailing list
Readable-discuss@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/readable-discuss


Re: [Readable-discuss] RESTART <*..*>

2013-01-16 Thread David A. Wheeler
Beni Cherniavsky-Paskin:
> "<*" is 2 chars, "((" is 2 chars.  Some of your win here is just from using
> spaces to set apart the delimiters.
> Isn't this better addressed by schemes that allow [..] in place of (..):
> 
> let [ (x cos(f(c)))
>   (y sin(f(c))) ]
> ! dostuff x y
> 
> which is more homoiconic by preserving the nesting level.
> I feel that let's structure is truly annoying, but it's not the notation's
> job to hide that if it becomes less homoiconic; I'd rather fix the
> construct and use a let1 macro.

I agree that let's structure in the 1-variable case is annoying (I also 
sometimes use a let1 macro), and I agree that it's not a notation's job to 
*hide* annoying structures.

But if a structure is common and annoying to *use*, it's reasonable to look for 
notations that make it *easier* to use.  Hiding bad, ease-of-use good :-).

> Personally I'm not (yet?) a big fan of $.

Not a problem.  It's grown on me.  Once you have it, you find that patterns 
where it applies are remarkably common.

> I have even more reservations about \\ usage:
>let <* x cos(f(c)) \\ y sin(f(c)) *>
> where the list depth hinges on the fact that there are 2 elements between the 
> \\.
> 
> I see how such constructs are appealing in-line once you're used to them,

I think that's the key point.  It needs to be easy for people to mentally map a 
construct to the underlying list structure, of course, but after a while, you 
learn that certain visual patterns are the "easy" way to use a construct.  The 
same thing happens in other languages; I read the following C construct:
  for (i=0; i < max; i++) ...
as a single trivial idea, because it's such a common pattern.

> but this makes me ask: could you lift $ and/or \\ to a separate layer from
> indent processing, so they remain available inside regular (..) lists?

Sure, that's possible.  But do we *want* to?
1. That would mean that you'd have to escape them even inside (...).
2. It mildly interferes with backwards compatibility.  I'd like traditional 
code to mostly work "as is" - in a backward-compatible way - if it's cleanly 
formatted.  Programs that use symbols $ or \\ would then have problems.
3. I'd like to be able to call down to the underlying reader as much as 
possible to implement constructs; doing this *requires* that we override 
processing the contents of a list, even if it already has a curly-infix reader.

> I must admit I haven't even tried to keep up with your grammar work.  I'll
> try to take a look - the whole thing is much shorter than the one-at-a-time
> mails made me think :-)

Thanks!

> I'm not against having a way to restart indentation; I just wanted to keep
> the *option* to not restart it to 0, as a matter of taste.
> Though in light of empty comments always being available, I'm ok with a
> construct that always forces indent to 0, if it's simpler.

It's much simpler.  There are some nasty subtleties in *starting* with a 
non-zero indent and trying to make it "mean the obvious" in a Lisp-based 
language; see the draft SRFI for more details if you're curious.  It could work 
in other languages, but in Scheme, it's hard because (1) the "read" interface 
of Scheme is already fixed, and (2) standard Scheme doesn't support unlimited 
unread-char.  

> Sure, it must be multi-char.  I was think more in the directions of e.g. #(
> ... )# but those might well be taken for things like vectors.

Yes, "#(" introduces a vector comment.  And "#" is busy enough; there are a lot 
of nonstandard Scheme extensions that start with "#", so anything starting with 
"#" is frankly not safe for use (it'd probably conflict with SOMETHING).

> Another very unbaked idea: perhaps we can take a hint from typography and
> formats such as reStructuredText, markdown and emacs outline-mode (which
> all took that hint):
> Represent most structure using indentation, but some structure above that
> using several levels of headings.

Not a crazy idea, but that would only deal with the case for multi-line that 
begins on the left edge.  That wouldn't deal with the "small let" case, or 
anything that has some simple prefix.  I know you don't care about "short let", 
but *I* do :-).

> I think like this direction on aesthetic grounds, but I suspect the
> practical convenience of having some reader macro entering the t-expr
> parser in the middle of s-expr parsing will prevail.

Yes, that's my thinking too.

--- David A. Wheeler

--
Master Visual Studio, SharePoint, SQL, ASP.NET, C# 2012, HTML5, CSS,
MVC, Windows 8 Apps, JavaScript and much more. Keep your skills current
with LearnDevNow - 3,200 step-by-step video tutorials by Microsoft
MVPs and experts. ON SALE this month only -- learn more at:
http://p.sf.net/sfu/learnmore_122712
___
Readable-discuss mailing list
Readable-discuss@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/readable-di

Re: [Readable-discuss] RESTART <*..*>

2013-01-16 Thread David A. Wheeler
Alan Manuel Gloria:
> Whoa whoa whoa - there seems to be problems with SUBLIST and SPLICE!

Are you suggesting there could be a... bug?!?  Why, that could never happen :-).

It appears that SUBLIST is the problem child here.  In "unsweeten", using just 
SUBLIST, we have (as expected):
amkg animals $ 1 0
==>
(amkg animals (1 0))


In the draft BNF, we have the unexpected:
amkg animals $ 1 0
==>
((amkg animals) (1 0))


If one pair of parens is good, I guess two is better :-).  This was made worse 
because my test suite "correct" answers had the wrong results. My bad, sorry.

Clearly the SUBLIST action is busted.  I believe this fixes it:

  | SUBLIST hspace* i_expr1=i_expr
-   {$v=list(monify($head.v), $i_expr1.v);}
+   {$v=append($head.v, list(monify($i_expr1.v)));}


I've posted the grammar with that change.

Okay, let's try again.  I took this:

<*
library \\ amkg animals $ 1 0
export
  cat
  rename $ rover dog
import
  only
amkg pets $ 1 0
rover

define cat 'meow

*>

The draft BNF now generates:
(library (amkg animals (1 0)) (export cat (rename (rover dog))) (import (only 
(amkg pets (1 0)) rover)) (define cat (quote meow)))

Which can be reformatted as:
(library
  (amkg animals (1 0))
  (export cat (rename (rover dog)))
  (import (only (amkg pets (1 0)) rover))
  (define cat (quote meow)))


Is that what you expected?

--- David A. Wheeler

--
Master Visual Studio, SharePoint, SQL, ASP.NET, C# 2012, HTML5, CSS,
MVC, Windows 8 Apps, JavaScript and much more. Keep your skills current
with LearnDevNow - 3,200 step-by-step video tutorials by Microsoft
MVPs and experts. ON SALE this month only -- learn more at:
http://p.sf.net/sfu/learnmore_122712
___
Readable-discuss mailing list
Readable-discuss@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/readable-discuss


Re: [Readable-discuss] RESTART <*..*>

2013-01-16 Thread Alan Manuel Gloria
On 1/17/13, David A. Wheeler  wrote:
> Alan Manuel Gloria:
>> So given the above semantics, we can define an R6RS library as so:
>>
>> <*
>> library \\ amkg animals $ 1 0
>> export
>>   cat
>>   rename $ rover dog
>> import
>>   only
>> amkg pets $ 1 0
>> rover
>>
>> define cat 'meow
>>
>> *>
>
> I just ran your same through my ANTLR processor, which now implements the
> "sequence of i_expr" semantics.  I still need to examine the draft action
> rules more carefully, but even so, it came up with this:
>
> (library
>   ((amkg animals) (1 0))
>   (export cat (rename (rover dog)))
>   (import (only ((amkg pets) (1 0)) rover))
>   (define cat (quote meow)))
>
> That certainly seems like a plausible interpretation of the example.  Do you
> agree?

Whoa whoa whoa - there seems to be problems with SUBLIST and SPLICE!

amkg animals $ 1 0
==>
(amkg animals (1 0))

remember:

define foo(x) $ cond
  { x = 0 } $ bar()
  else  $ core-foo x

==>

(define (foo x) (cond
  ((= x 0) (bar))
  (else (core-foo x

So the ((amkg animals) (1 0)) looks wrong here.

In fact:

library \\ amkg animals $ 1 0

...should be equivalent to:

library
amkg animals $ 1 0

...should be equivalent to:

library
amkg animals
  1 0

...And then:

library
(amkg animals
  (1 0))

So something looks wrong

Sincerely,
AmkG

--
Master Visual Studio, SharePoint, SQL, ASP.NET, C# 2012, HTML5, CSS,
MVC, Windows 8 Apps, JavaScript and much more. Keep your skills current
with LearnDevNow - 3,200 step-by-step video tutorials by Microsoft
MVPs and experts. ON SALE this month only -- learn more at:
http://p.sf.net/sfu/learnmore_122712
___
Readable-discuss mailing list
Readable-discuss@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/readable-discuss


Re: [Readable-discuss] RESTART <*..*>

2013-01-16 Thread Beni Cherniavsky-Paskin
On Jan 16, 2013 3:29 PM, "David A. Wheeler"  wrote:
>
> > 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.
>
I'll defer to you on this though I don't feel this is such a big problem in
python; GUI shells solve it by distinguishing pressing Enter from pasting
Enter, and/or by requiring ctrl+Enter (or backspacing the indent then
Enter) to terminate multiline command (IIRC dreampie does the latter).
Unfortunately, lisp doesn't have python's : hint that the expression will
be a multiline one.

It's indeed annoying in the terminal.  IIRC ipython has some magic %paste
syntax to paste an arbitrary block.  IOW, the file/repl tension does
justify a construct like this, but it's a REPL only construct...

> 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.
>
Ah, indeed I missed that!
It changes a lot of priorities in my arguments, because if I'd keep the
indentation and only use this for empty lines, that feels a  petty -
perhaps I should just live with empty comments and not need a new construct
at all; and let people who also want to reset indentation have their way...

> 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".
>
Agreed.  I absolutely hate SQL prompts that don't execute until I add a ;

> 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 languages.
>
> Contrast:
>
> let ((x cos(f(c
> ! dostuff x
>
> with:
> 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.
>
"<*" is 2 chars, "((" is 2 chars.  Some of your win here is just from using
spaces to set apart the delimiters.
Isn't this better addressed by schemes that allow [..] in place of (..):

let [ (x cos(f(c)))
  (y sin(f(c))) ]
! dostuff x y

which is more homoiconic by preserving the nesting level.
I feel that let's structure is truly annoying, but it's not the notation's
job to hide that if it becomes less homoiconic; I'd rather fix the
construct and use a let1 macro.

> or:
> let <* x $ cos $ f c *>
> ! dostuff x
>
Personally I'm not (yet?) a big fan of $.
I have even more reservations about \\ usage:
   let <* x cos(f(c)) \\ y sin(f(c)) *>
where the list depth hinges on the fact that there are 2 elements between
the \\.

I see how such constructs are appealing in-line once you're used to them,
but this makes me ask: could you lift $ and/or \\ to a separate layer from
indent processing, so they remain available inside regular (..) lists?

> 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 must admit I haven't even tried to keep up with your grammar work.  I'll
try to take a look - the whole thi

Re: [Readable-discuss] RESTART <*..*>

2013-01-16 Thread David A. Wheeler
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 <* ... *> 
proposal.


> > 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 
languages.

Contrast:

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

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

or:
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 <* ... *> we

Re: [Readable-discuss] RESTART <*..*>

2013-01-16 Thread Beni Cherniavsky-Paskin
On Jan 15, 2013 2:57 PM, "David A. Wheeler"  wrote:
> Sweet-expressions without restart lists (<* ... *>)
> work well in a vast number of circumstances.
> However, they can be somewhat awkward for two typical use cases:
> 
> 
> A long sequence of definitions contained within an initial statement.
> This situation occurs in many library definition structures such as
> Scheme R7RS define-library and in some larger data
structures.
> A let-style statement with one or two variables
> with short initial values.
> 

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.

> 
> Let's begin with the first use case.
> When there is a long sequence of definitions contained within an
> initial statement, and no special notation like restart lists,
> all the definitions in the long sequence must be
> indented and none can be separated by a blank line
> (since that would end the entire sequence, not just a definition).
> Indenting almost an entire file is annoying, and needing no blank lines
> for that long invites mistakes.

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?

>...
> 
> 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)
> it can take up more vertical space than traditional formatting.
> Using a leading "$" takes up somewhat less vertical space, but it still
> takes up an additional line for a trivial case, it does not work
> the same way for let expressions with 2 variables,
> and David A. Wheeler thinks it is a rather unclear construction.
> You can also use parenthetical notation directly, but this is
> relatively ugly and it is annoying to need to do this for a common case.

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.

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.

>...
> let  ; Using \\ takes up a lot of vertical space in simple cases
>   \\
> x 5
>   {x + x}
>
> let
>   \\
> x 5
> y 7
>   {x + x}
>
> let  ; Less vertical space, but 1 variable only
>   $ x 5
>   {x + 5}
>
> ; Note "$ x 5 $ y 7" isn't right; that maps to ((x 5 (y 7))).
>...

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.
IMO this goes deeper than just let but I don't think abusing <*..*> is an
improvement.  I'll try to post thoughts on this in the z language thread.

> 
> Here are examples of the same constructs, using restart lists:
> 
> 
> 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)))
> ...
> *>
>
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!

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

> 
> The restart list symbols are carefully chosen.
> The characters < and > are natural character pairs that are
> available in ASCII.
> What is more, they are not delimiters, so any underlying
> Scheme reader will not immediately stop on reading them
> (making it easier to reuse).

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.

Which leads me to the following idea: let the list be started / ended by
(...), but have a notation that *only* [re]starts t-exp

Re: [Readable-discuss] RESTART <*..*>

2013-01-16 Thread David A. Wheeler
Alan Manuel Gloria:
> So given the above semantics, we can define an R6RS library as so:
> 
> <*
> library \\ amkg animals $ 1 0
> export
>   cat
>   rename $ rover dog
> import
>   only
> amkg pets $ 1 0
> rover
> 
> define cat 'meow
> 
> *>

I just ran your same through my ANTLR processor, which now implements the 
"sequence of i_expr" semantics.  I still need to examine the draft action rules 
more carefully, but even so, it came up with this:

(library
  ((amkg animals) (1 0))
  (export cat (rename (rover dog)))
  (import (only ((amkg pets) (1 0)) rover))
  (define cat (quote meow)))

That certainly seems like a plausible interpretation of the example.  Do you 
agree?

--- 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:
http://p.sf.net/sfu/learnmore_122612 
___
Readable-discuss mailing list
Readable-discuss@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/readable-discuss


Re: [Readable-discuss] RESTART <*..*>

2013-01-16 Thread David A. Wheeler
Alan Manuel Gloria:

> 2.  "superlist" just calls the top-level "i_expr" repeatedly, creating
> a list of items, and terminating upon finding a *>, returning the
> yielded list.

I had originally done this, and I then switched over to a more complicated set 
of productions.  I've now recently switched back to that much simpler "sequence 
of i_expr" semantic, and I think that's the "right" meaning.  I've posted my 
latest to the devel branch in our SourceForge git repository.

Sadly, there's an annoying tooling problem with treating superlist/restart 
list/whatever as just a "sequence of i_expr", which is why I had switched from 
the simple sequence to a more complicated set of productions.  To make the 
"sequence of i_expr" concept work, you have to be able to end a restart list on 
the *SAME LINE* that it starts.  Previously, an i_expr could *ONLY* end at the 
end of a line (possibly preceded by ";", and given the exception of the special 
case of splice).  Because that was true, that made for a really clear potential 
ending point for an i_expr (in the normal case).  No big deal, you say, just 
add a new branch in i_expr to allow "head empty".  Well, yes, and I've done 
that.  However, once you do that, ANTLR generates a huge number of warnings 
about various ambiguities.

As far as I can tell, the ANTLR warnings are technically correct but spurious.  
There's a huge number of them, and they're painful to track through.  But if I 
understand them correctly, the issue is straightforward.  If you allow "head 
empty" to end an i_expr, that means that *any* sequence of one or more n_expr 
on a line could end an i_expr, because any sequence of one or more n_expr can 
be a head.  So technically "a b" and "a" both match an i_expr if "head empty" 
is allowed as an i_expr.

This is basically the same situation as the "trailing else" matching in many 
programming languages.  It's also trivially disambiguated, just like "trailing 
else".  In this case, if you are reading in a line, simply follow the longest 
match, or the earliest matching branches in a production where more than one 
case could match, to disambiguate the cases.  In fact, ANTLR does this, and it 
seems to work just fine.

What's *weird* is that I can't seem to get ANTLR to shut up about it when it 
generates the grammar.  ANTLR has a "greedy" option specifically to disable 
warnings when you want it to disambiguate branches this way.  But in this case 
I can't seem to make ANTLR happy.  That makes *me* sad, because I'd like as 
much confidence as possible that the specification is right, and I've been 
using ANTLR to help me gain that confidence.  ANTLR's greedy option works in 
other cases, so I'm not sure why it's ignoring me in this case.

That said, I think this "sequence of i-expression" semantic is pretty clearly 
the right semantic.  For one thing, the productions I come up with are simple 
and clean.  I haven't checked the action rules carefully yet, but my first try 
at them seems reasonably right too.  It seems to be easy to reason about and 
produce the "expected results".  Here's my current try, fixes welcome:

restart_tail returns [Object v]:
  i_expr rt1=restart_tail {$v = cons($i_expr.v, $rt1.v);}
  | RESTART_END {$v = null;} ;

restart_list returns [Object v]:
  RESTART hspace* comment_eol* restart_tail {$v = $restart_tail.v;} ;

head returns [Object v] ...
 | restart_list hspace*
 (rest1=rest {$v = cons($restart_list.v, $rest1.v) ; }
  | empty{$v = list($restart_list.v); } )

rest returns [Object v] ...
  | restart_list hspace*
(rest2=rest {$v = cons($restart_list.v, $rest2.v);}
 | empty {$v = list($restart_list.v);} )

i_expr returns [Object v]
  : head  ...
 | empty {$v = monify($head.v);} /* "head empty" - RESTART_END next */ ))
  ...

Thoughts?

--- 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:
http://p.sf.net/sfu/learnmore_122612 
___
Readable-discuss mailing list
Readable-discuss@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/readable-discuss


Re: [Readable-discuss] RESTART <*..*>

2013-01-16 Thread Alan Manuel Gloria
> Okay here's the concrete semantics I propose:
>
> 1.  The "head" production is the part that looks for the <*.  Upon
> finding a <*, it consumes any number of horizontal spaces, line
> comments, and multiline/datum comments.  It then enters "superlist"
> production
>
> 2.  "superlist" just calls the top-level "i_expr" repeatedly, creating
> a list of items, and terminating upon finding a *>, returning the
> yielded list.
>
> 3.  When "superlist" returns, "head" just takes its returned value and
> takes it as a single item, and continues on its merry way looking for
> n-expressions and superlists after the *>.
>
> The third part allows:
>
> let <* x 5 \\ y 6 *> {x + y}


So given the above semantics, we can define an R6RS library as so:

<*
library \\ amkg animals $ 1 0
export
  cat
  rename $ rover dog
import
  only
amkg pets $ 1 0
rover

define cat 'meow

*>

Thoughts?

Sincerely,
AmkG

--
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:
http://p.sf.net/sfu/learnmore_122612 
___
Readable-discuss mailing list
Readable-discuss@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/readable-discuss


Re: [Readable-discuss] RESTART <*..*>

2013-01-16 Thread Alan Manuel Gloria
On 1/16/13, David A. Wheeler  wrote:
> Alan Manuel Gloria:
>
>> Okay, the *semantics* is confusing to me.
>>
>> How are the following suppose to parse?
>
> The answer is, "whatever we decide it should be" :-).  So now is a perfect
> time to discuss it.  And if some combination seems to be nonsense, we can
> declare it an error.
>
> BTW, Don't pay serious attention to the sweet.g file's action statements for
> restart_list.  I'm doing a lot of experiments with them and they're almost
> certainly "wrong" right now.  So with that caveat...
>
>> library foo
>>   <* begin
>>
>> define cat 'meow
>>
>> define dog 'woof
>>
>> *>
>>
>> I assume:
>>
>> (library foo
>>   (begin
>> (define cat 'meow)
>> (define dog 'woof)
>> )
>
> Yes, that's what I think too.
>
> But that's if we allow same-line and later-lines simultaneously at *all*.
> My current draft BNF *does* allow this (by intent), but if the semantics are
> too complicated, we could just say either (1) it must be all on one line, or
> (2) the start has to be followed by hspace* comment_eol.
>
> But let's continue the thought...
>
>> But what happens with this?
>>
>> library foo
>>   <* begin print(x)
>>
>> define cat 'meow
>> define dog 'woof
>>
>> *>
>
> To be honest, I don't know of a use case that suggests any particular
> semantic.  I can image that this *might* mean:
>
> (library foo
>   (begin
> (print x)
> (define cat 'meow)
> (define dog 'woof)))
>
> Though perhaps other semantics would make sense.
>
>> How about this?
>>
>> let <* x 5 *> { x + 42 }
>
> I think t that should mean:
>   (let ((x 5)) (+ x 42)
>
> Basically, <*...*> wraps an extra () around an expression. Since "x 5" means
> (x 5), "<* x 5 *>" == ((x 5)).  And since what follows <*...*> is just
> another parameter, that parameter should be treated normally.
>
>> Or worse, this?
>>
>> let <*x y
>>w z *>
>>   42
>
> I'm guessing that should perhaps be:
> (let (x y (w z)) 42)
>
> Perhaps we'd better off to not allow stuff to be on both the same line and
> on later lines, at least at first.  The "library definition" use case and
> the "let" use case are easily distinguished that way.  That might mean you'd
> have a multi-line statement with a "begin" on its own line, but if it's a
> long sequence of definitions, that may not be a big deal.
>

Okay here's the concrete semantics I propose:

1.  The "head" production is the part that looks for the <*.  Upon
finding a <*, it consumes any number of horizontal spaces, line
comments, and multiline/datum comments.  It then enters "superlist"
production

2.  "superlist" just calls the top-level "i_expr" repeatedly, creating
a list of items, and terminating upon finding a *>, returning the
yielded list.

3.  When "superlist" returns, "head" just takes its returned value and
takes it as a single item, and continues on its merry way looking for
n-expressions and superlists after the *>.

The third part allows:

let <* x 5 \\ y 6 *> {x + y}

>> You know, maybe we should call it "SUPERLIST" in contrast with "SUBLIST".
>> ^^;;;
>
> You're smiling, but that's not an entirely insane name.  It's hard to think
> of a good name for this.

MEGALIST
UBERLICHST
OVERLYPRETENTIOUSADJECTIVELIST

Sincerely,
AmkG

--
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:
http://p.sf.net/sfu/learnmore_122612 
___
Readable-discuss mailing list
Readable-discuss@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/readable-discuss


Re: [Readable-discuss] RESTART <*..*>

2013-01-15 Thread David A. Wheeler
Alan Manuel Gloria:

> Okay, the *semantics* is confusing to me.
> 
> How are the following suppose to parse?

The answer is, "whatever we decide it should be" :-).  So now is a perfect time 
to discuss it.  And if some combination seems to be nonsense, we can declare it 
an error.

BTW, Don't pay serious attention to the sweet.g file's action statements for 
restart_list.  I'm doing a lot of experiments with them and they're almost 
certainly "wrong" right now.  So with that caveat...

> library foo
>   <* begin
> 
> define cat 'meow
> 
> define dog 'woof
> 
> *>
> 
> I assume:
> 
> (library foo
>   (begin
> (define cat 'meow)
> (define dog 'woof)
> )

Yes, that's what I think too.

But that's if we allow same-line and later-lines simultaneously at *all*.  My 
current draft BNF *does* allow this (by intent), but if the semantics are too 
complicated, we could just say either (1) it must be all on one line, or (2) 
the start has to be followed by hspace* comment_eol.

But let's continue the thought...

> But what happens with this?
> 
> library foo
>   <* begin print(x)
> 
> define cat 'meow
> define dog 'woof
> 
> *>

To be honest, I don't know of a use case that suggests any particular semantic. 
 I can image that this *might* mean:

(library foo
  (begin
(print x)
(define cat 'meow)
(define dog 'woof)))

Though perhaps other semantics would make sense.

> How about this?
> 
> let <* x 5 *> { x + 42 }

I think t that should mean:
  (let ((x 5)) (+ x 42)

Basically, <*...*> wraps an extra () around an expression. Since "x 5" means (x 
5), "<* x 5 *>" == ((x 5)).  And since what follows <*...*> is just another 
parameter, that parameter should be treated normally.

> Or worse, this?
> 
> let <*x y
>w z *>
>   42

I'm guessing that should perhaps be:
(let (x y (w z)) 42)

Perhaps we'd better off to not allow stuff to be on both the same line and on 
later lines, at least at first.  The "library definition" use case and the 
"let" use case are easily distinguished that way.  That might mean you'd have a 
multi-line statement with a "begin" on its own line, but if it's a long 
sequence of definitions, that may not be a big deal.

> You know, maybe we should call it "SUPERLIST" in contrast with "SUBLIST". 
> ^^;;;

You're smiling, but that's not an entirely insane name.  It's hard to think of 
a good name for this.

--- 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:
http://p.sf.net/sfu/learnmore_122612 
___
Readable-discuss mailing list
Readable-discuss@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/readable-discuss


Re: [Readable-discuss] RESTART <*..*>

2013-01-15 Thread Alan Manuel Gloria
Okay, the *semantics* is confusing to me.

How are the following suppose to parse?

library foo
  <* begin

define cat 'meow

define dog 'woof

*>

I assume:

(library foo
  (begin
(define cat 'meow)
(define dog 'woof)
)

But what happens with this?

library foo
  <* begin print(x)

define cat 'meow
define dog 'woof

*>
How about this?

let <* x 5 *> { x + 42 }

Or worse, this?

let <*x y
   w z *>
  42

Sincerely,
AmkG

P.S.
You know, maybe we should call it "SUPERLIST" in contrast with "SUBLIST". ^^;;;

--
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:
http://p.sf.net/sfu/learnmore_122612 
___
Readable-discuss mailing list
Readable-discuss@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/readable-discuss


Re: [Readable-discuss] RESTART <*..*>

2013-01-15 Thread Alan Manuel Gloria
The bit: ; Note "$ x 5 $ y 7" isn't right; that maps to ((x 5 (y 7))).

..should be better placed in a paragraph - I for one tend to skim over
source code in the SRFI.

--

The bit: Changing all of sweet-expressions, just to handle this particular case,
does not seem warranted.

...this doesn't seem to scan well.  It seems to introduce an argument
to support a position (don't change all of sweet-expressions) but the
paragraph it's in doesn't look like it introduces the opposing
position.

--

You might want to juxtapose:

let
  \\
x $ foo bar
  use x

versus:

let <* x $ foo bar *>
  use x

I suggest you use something similar to what you did in
readable.sourceforge.net: use a table so that both examples are
side-by-side.

I also suggest using the given example above rather than (let ((x 5))
(+ x x)), since it gives a better justification for using RESTARTBEGIN
/ RESTARTEND : We want to use "foo bar" not "foo(bar)" for stylistic
reasons (i.e. foo is a "command" whose return status we want to know,
not a "function" that just computes something).

--

This bit:   begin <*

Looks wrong.  Shouldn't that be: <* begin ??

Of course, it depends on what, exactly, is meant by <* *>.  So maybe:
"begin . <*" ??

Sincerely,
AmkG

--
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:
http://p.sf.net/sfu/learnmore_122612 
___
Readable-discuss mailing list
Readable-discuss@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/readable-discuss


Re: [Readable-discuss] RESTART <*..*>

2013-01-15 Thread David A. Wheeler
Okay, I've tried to write down my thoughts on WHY I think restart lists are a 
good idea.

Comments welcome.  A better name is welcome for sure :-).

BTW, I have a draft BNF and action rules, but don't take them seriously for 
restart lists; I used them more for experimentation.

--- David A. Wheeler



Restart lists (<* ... *>)

Sweet-expressions without restart lists (<* ... *>)
work well in a vast number of circumstances.
However, they can be somewhat awkward for two typical use cases:


A long sequence of definitions contained within an initial statement.
This situation occurs in many library definition structures such as
Scheme R7RS define-library and in some larger data structures.
A let-style statement with one or two variables
with short initial values.


Let's begin with the first use case.
When there is a long sequence of definitions contained within an
initial statement, and no special notation like restart lists,
all the definitions in the long sequence must be
indented and none can be separated by a blank line
(since that would end the entire sequence, not just a definition).
Indenting almost an entire file is annoying, and needing no blank lines
for that long invites mistakes.



For example, here's an example from the R7RS Scheme specification
for define-library:

(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)))
(do ((i 0 (+ i 1)))
((= i n) grid)
  (let ((v (make-vector m #f alse)))
(vector-set! grid i v)
(define (rows grid) (vector-length grid))
(define (cols grid)
  (vector-length (vector-ref grid 0)))
(define (ref grid n m)
  (and (< -1 n (rows grid))
   (< -1 m (cols grid))
   (vector-ref (vector-ref grid n) m)))
(define (put! grid n m v)
  (vector-set! (vector-ref grid n) m v


This is easily reformatted into this sweet-expression:


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)))
do (i(0 {i + 1}))
! {i = n} grid
! let (v(make-vector(m #f alse))) vector-set!(grid i v)
define rows(grid) vector-length(grid)
define cols(grid) vector-length(vector-ref(grid 0))
define ref(grid n m)
  and
{-1 < n < rows(grid)}
{-1 < m < cols(grid)}
vector-ref vector-ref(grid n) m
define put!(grid n m v) vector-set!(vector-ref(grid n) m v)



But there are reasons that sweet-expressions are defined the way they are.
It is fundamental that a child line is indented from its parent, since
that is the point of indentation.
Opening a parentheses intentionally disables indentation processing;
this is what developers typically expect (note that both Python and
SRFI-49 do this), and it also makes sweet-expressions very
backwards-compatible with traditional s-expressions.
Ending a definition at a blank line is very convenient for interactive use,
and interactive and file notation should be identical
(since people often switch between them).
Changing all of sweet-expressions, just to handle this particular case,
does not seem warranted.



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)
it can take up more vertical space than traditional formatting.
Using a leading "$" takes up somewhat less vertical space, but it still
takes up an additional line for a trivial case, it does not work
the same way for let expressions with 2 variables,
and David A. Wheeler thinks it is a rather unclear construction.
You can also use parenthetical notation directly, but this is
relatively ugly and it is annoying to need to do this for a common case.
A similar argument applies to do-expressions, and these are
not at all unusual in Scheme code:


let  ; Using \\ takes up a lot of vertical space in simple cases
  \\
x 5
  {x + x}

let
  \\
x 5
y 7
  {x + x}

let  ; Less vertical space, but 1 variable only
  $ x 5
  {x + 5}

; Note "$ x 5 $ y 7" isn't right; that maps to ((x 5 (y 7))).

; The two-variable format can be surprising and does not let the
; programmer emphasize the special nature of the variable assignments
; (compared to the later expressions in a let statement).
let
  x(5) y(7)
  {x + 5}

let (x(5)) ; Use parentheses
  {x + x}
let (x(5) y(7))
  {x + x}



A restart list is surrounded by the markers <* and *>.
The <* and *> represent opening and closing
parentheses, but restart indentation processing
at the left edge instead of disabling indentation processing.
The purpose of restart lists is to make it easy to clearly
express these and similar use cases.



In a restart list, the rest of the text after the initial <*
is treated specially.
That'