[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: how useful are collecting lists?



David Vanderson:
> I'm very interested in sweet-expressions - thank you!  I'm already sold 
> on curly-infix, neoteric, indentation, and SUBLIST.

Awesome!  That's a big step!

>  I'd like to ask  about collecting lists.
> 
> Collecting lists seem to have small importance in the SRFI, and it's not 
> obvious that they are warranted given the rational in the SRFI. Also 
> they are unused in both example programs (sweeten and letterfall).

Collecting lists are the most recent addition to the notation,
and were added after sweeten and letterfall were written.
So they're unused for simple reason that, at the time, they didn't exist.

That said, I could go back to "sweeten" and add a few uses of
collecting lists, to show their use in practice.  Sounds reasonable enough,
at least to demonstrate utility.

> Given this, I don't understand their inclusion in the SRFI.  What am I 
> missing?

The rationale for collecting lists is here:
http://srfi.schemers.org/srfi-110/srfi-110.html#collecting-lists

The rationale notes two use cases:
1. 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.
2. A let-style statement with one or two variables with short initial values.

Use case #1 only becomes obvious when you try to create long definition sequences, e.g., library modules.  (An aside: This is why I think it's important to write "real programs" in proposed notations; some problems only become visible when you try to "scale up").

Alan Manuel K. Gloria first noticed that when you created a long sequence of definitions-in-definitions of data, sweet-expressions would still *work* but would be less than optimal.  I then noticed that the same problem in library definitions.    This had been obscured in part by our desire to try to stick with portable Scheme constructs; nearly every Scheme has a library module construct, but none are universal (some use R6RS, many don't).  I really hope that R7RS fixes this (by making a library module construct available widely).  In any case, there's clearly a need for a way to easily handle library modules with many embedded definitions, or any other data structure with long structures-in-structures.

Without collecting lists, if you have a long multi-page library module definition, you'll typically have multiple indents before you can even start actually defining things.  That loses some horizontal space.  Also, there's the risk of accidentally inserting a blank line, which would end the entire library module definition (not just that definition).  We could change the meaning of blank line, but that then interferes with interactive use.

Use case #2 happens quite a bit in Lisp-based languages.  It's often the case that you want to use "let" to define/compute just 1-2 variables, followed quickly by the body.  You can do this with traditional s-expressions, but when the value itself uses parens, this isn't so clear.
E.G., in sweeten, we currently have:
    let* (asunit-car(exposed-unit(car(m))))
I think this is more clearly expressed as:
    let* <* asunit-car exposed-unit(car(m)) *>
or:
    let* <* asunit-car $ exposed-unit car(m) *>
Parenthesis do not kill anyone, and are obviously very useful... but a whole batch of closing parens (4 in this case) can easily hide problems (should it be 3? 5?).

The same is true for this line in sweeten.sscm:
    ! ! let* (asline-cuddled(line(list(car(m) cadr(m)))))
Again, quite a march of closing parens at the end.  We can instead write:
    ! ! let* <* asline-cuddled $ line list(car(m) cadr(m)) *>

Another line:
    let* (asline(line(m)) length-asline(length(asline)))
can be:
    let* <* asline$ line m \\ length-asline $ length asline  *>
Note that in this case, it's way more obvious that we have a 2-variable case, not a 1-variable case.

--- David A. Wheeler