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

Re: how useful are collecting lists?

On 3/13/13, David A. Wheeler <dwheeler@xxxxxxxxxxxx> wrote:
> David Vanderson:
>> > 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.
>> >
>> I think #1 is a decent rationale, and with some experimenting I'm
>> starting to see how collecting lists are useful there.  To make sure I
>> understand, it seems like the primary motivation here is the
>> "unintentional blank line" problem:
>> define foo(x)
>>    define bar(y)
>>      y
>>    define baz(z)
>>      z
>> This works in a Python script, but not at the REPL.  To avoid that
>> behavior, when using sweet expressions you either have to remove blank
>> lines:
>> define foo(x)
>>    define bar(y)
>>      y
>>    define baz(z)
>>      z
>> Or you must manually insert \\:
>> define foo(x)
>>    define bar(y)
>>      y
>>    \\
>>    define baz(z)
>>      z
>> Are those the only options without collecting lists?  If so, I can
>> understand the motivation.
> Yes, that's right.  Without collecting lists,
> those are the only options... and that's the motivation.

There's another, the comment-only blank line, which is the "quietest"
blank line replacement:

define foo(x)
! define bar(y)
! ! y
! define baz(z)
! ! z
! whatever
! ...

>> In my examples, define has an implicit begin.  In this situation, I'm
>> unsure how to use <*, because it introduces an extra parenthesis.  Have
>> you run into this problem?
> I've intentionally defined <* to ALWAYS create another open paren.
> I think that's easier to understand, and it also makes it really helpful
> in short lists.
> I haven't worried about the define-in-define case above, because the
> long-and-annoying constructs that we've seen so far (as use cases)
> always had some sort of list that <*...*> easily mapped to.
> Of course, maybe that's a limitation of the use cases we've discussed!
> Hmm. If that's a *problem*, one solution without significantly changing
> the existing semantics might be to allow <*...*> after ".".  I suspect
> such cases would basically just continue a list.  Here's what I have in
> mind:
> define foo(x) . <*
> define bar(y)
> ! y
> define baz(z)
> ! z
> ! *>
> ; ==> (define (foo x) (define bar(y) y) (define baz(z) z))
> So... does anyone have thoughts about this?  Is this an important case?
> If it is, then is this a solution?  Are people running to the exits?
> Other thoughts?

Ara ara, I thought this was *already* allowed.  Basically, what you're doing is:

(define (foo x) . (
(define (bar y)
(define (baz z)

... which should work without any modifications to the spec.


Personally, even in my s-expressions era I started to dislike
deeply-nested definitions.  I had a program once (which was really a
metaprogram that analyzed another program (a user script actually) in
order to track particular usage patterns so that it could emulate its
execution in a more restricted environment, woof woof) that had
functions within functions within functions (I think I had five levels
max) - the number of indents was amazingly deep.

Now I prefer to have reasonably shallow function definitions (at most
a single define-in-define) and just depend on the module system to
hide the bits I'm not interested in exposing to the rest of the
program (a habit I picked up from Haskell, LOL).  I couldn't do that
in my described 5-level-deep-defines program because it was written in
a Scheme-like language without modules, so to reduce namespace
pollution I had to use such deep defines.

That and a lack of experience, actually (^^) I now know that such deep
defines are a *pain* to debug.