On 2/11/13, Arne Babenhauserheide <arne_...@web.de> wrote:
> Hi Alan,
> (I’m answering to both mails here)
> Am Montag, 11. Februar 2013, 11:07:30 schrieb Alan Manuel Gloria:
>> Your main contributions seem to be the extended "." behavior (. a =>
>> a, . a b -> a b) and the ":" syntax.  I don't see any use, even in
>> your examples, of the single-item-on-a-line-is-single-item-list
>> behavior.
> The reason for that is consistency: Making sure that when you learn a
> minimal set of rules you can understand the structure of all code you see.

Consistency and convenience are both needed in a notation.  The key is
to find the balance between both.  I think in this case, the
single-item case tends to occur more often than the
single-item-function-call case.

Even for preprocessing, consider the following rule:

A line is considered a "single-item line" if:
1.  Strip trailing and leading spaces from the line.
2.  If there are any spaces inside the line that are outside matched
() [] {} "" #||#, it is not a single-item line.
3.  Newlines/EOL inside matching () [] {} "" #||# are  considered
spaces and do not "terminate" the line.

So even if you insist on a separate preprocessing pass rather than a
full parser, it's possible to still correctly process the

>> That's fine and all, but suppose I'm defining a method for Guile GOOPS?
>> define-method : hack (x <cat>)
>> !             do-hack-on-cat x
>> Oops, except hack only works on cats anyway, so I'll just optimize
>> things (because profiling shows that method calls in GOOPS take up all
>> my time, LOL) and turn hack into an ordinary function:
>> define : hack x
>> !             do-hack-on-cat x
>> Oh, no!!  Now I have to adjust the indentation of everything inside
>> it!  Luckily hack x just contains do-hack-on-cat, so all I need to do
>> is adjust that single line.
>> define : hack (x <cat>)
>> !      do-hack-on-cat x
> Well, I’m a Python-Programmer. In Python you run into that everytime you
> remove or add an if. Before I used rectangle-edit, it disturbed me a bit.
> Now it’s quite painless:
> C-SPACE M-↓ ↑ C-7 → C-x C-r C-k

The example I show is worse, because it doesn't apply to just if: it
applies to every misspelled token.

Although ....

> There would be a simple way to fix it, though: Make the position of : only
> significant when you want to indent deeper. To make this consistent: Make
> the indentation of a line only relevant for deeper nested lines (child
> lines). Then the following would all be valid code:
> if : = a 1
>    b
>   c
> if
>     = a 1
>     b
>   c
> if : = a 1
>   b
>   c
> if
>     = a 1
>   b
>   c
> If the indentation is equal or lower than a previous indentation layer, the
> bracket of that indentation layer gets closed.

I see.  This does lessen (but not remove) problem #1.

>> 3.  You need to explicitly specify how double-width CJK characters are
>> handled when found before a ":" (ban them in code?  But what about
>> strings and #| |# comments?).  Do we treat them as single character
>> columns (easy implementation, but potentially confusing, and possibly
>> limiting international code) or do we treat them as double character
>> columns (need to consider encoding, and implementations need to keep a
>> list of all such double-width characters)?
> Being able to reduce indentation of later lines (as long as they stay child
> lines) would also solve this for most cases.

Please tell me: what should an implementation do when a double-width
CJK character is encountered?  Treat it as a +1 column position or +2
columns position?

At the very least, say "+1 column position, so people should avoid
using a : followed by a line more-indented than the : after a
double-width character, as it would be confusing."  Unless you're
willing to pay the price of every implementation keeping a list of
each double-width character.

>> ":" seems to put a lot of pressure on implementations, using your
>> current explanation.  Perhaps we can change ":" to be more local (i.e.
>> it won't require keeping track of column position, and won't cause
>> cascading affects when text before it changes)?
> For me the inline : mainly exists for consistency: It generalizes GROUP.
> Essentially GROUP adds a new indentation layer, so you could just allow
> using it inline. But I use : for group, because I think that \\ looks alien
> to normal text and so it hampers readability for all people who aren’t used
> to bash-escaping.

Our current semantic has settled on GROUP/SPLIT, not GROUP.  So:

; Arc
  cond1 \\ consequent 1
  cond2 \\ consequent 2
  \\       else-consequent 3
  cond1 (consequent 1)
  cond2 (consequent 2)
  (else-consequent 3))

The advantage of using GROUP/SPLIT rather than a separate GROUP and
SPLIT is that \\ can be used to "spoof" such constructs as above.
Basically, to "line up" the else-consequent together with its buddies
in the Arc example.  Compare the Scheme:

; Scheme
  cond1 $ consequent 1
  cond2 $ consequent 2
  else  $ else-consequent 3
  (cond1 (consequent 1))
  (cond2 (consequent 2))
  (else  (else-consequent 3)))

There's a reason why \\ and $ are defined the way they are, and that
is because they are duals (in the above sense) of one another.  One is
used for explicit list pairing ($) the other is used for implicit
list-pairing a la keywords and Arc if (\\)

> Inline : has nice features - if used sparingly - and I think it improves the
> readability of function definitions a lot. But if it were not necessary for
> double brackets, I would not propose adding it.
> Indentation based lisp syntax MUST support double brackets. That’s why :
> exists. Also it MUST support continuing the parameter list after a function
> call. That’s why . exists.
> Am Montag, 11. Februar 2013, 12:23:20 schrieb Alan Manuel Gloria:
>> 2.  It seems that multiple ": " at the start of each line are ignored,
>> and only the last one is used.  So the following is possibly (?)
>> valid:
>> define foo(bar)
>> : cond
>> : : meow?(bar)
>> : : : cat bar
>> : : woof?(bar)
>> : : : dog bar
>> : : else
>> : : : error 'foo "error!"
> It’s not valid, since the “: cond” would start at the same indentation as
> the define, but the converter would process it. So this is a bug in the
> converter…


>> How about this semantic instead?
>> ":" introduces a (, and a promise to add ) at the end of that line.
> To make it more general, you can add that the ) is added before the first
> less or equally indented line, but that a later line can add a new
> indentation layer.

I'm trying to make : more local here.  ":" with the "generalized" form
makes implementing a reader more difficult, xref. the need to
re-implement string, number, symbol, and even () #() #t #f parsing.

I guess you're more towards "preprocess only" without actually
replacing the reader.

I suggest looking at Haskell's layout rules, which have a similar
"preprocess only" for layout (except the bit about "if error insert

> That would give the full behaviour (defining an indentation layer) while
> keeping the enhanced readability for deeply nested functions.
>> In the first place, ":" can't support the shown cond-pattern.  So
>> without $, it would look like (without probe):
>> define-stream stream-map(f s)
>>   cond
> …
>> With probe:
>> define-stream stream-map(f s)
>>   probe
>>     cond
> …
> I think I see the merit of $ now: It wraps the rest of the code in a
> function call.

Yes.  SUBLIST is useful in many, many places.

>> A new synthesis?
>> Perhaps we can *keep* GROUP/SPLIT \\, SUBLIST $, and COLLECTINGLIST <*
>> *>, use the EXTENDPERIOD . a b, and add the new LINELIST :
> …
>> what you think?
> That would be the exact opposite of why I wrote. Instead of having 3 syntax
> elements, we now have 4 plus the . (which is just a generalization of (.
> a)).
> My intention was not to add more syntax overhead, but to reduce it by
> generalizing existing functionality.

*shrug*.  $ is not reducible to : - xref. above.  Consider also that $
is useful for other forms that could usefully get only one argument,
but that argument usually is a complex thingy.  Such as:

call/cc $ lambda (return)
  blah ... return(42) blah ...
delay $ let
  ! x $ whatever
  blah ...
delay-force $ cond
  stream-null?(whatever) $ blah ...
  else $ blah ...

So I don't see : displacing $.  You can't say:

call/cc : lambda (return)
  blah .. return(42) blah ...
Because it parses to:

(call/cc (lambda (return))
  (blah ... return(42) blah...))

To use it as a "$" replacement, you need to indent a *lot*.  $ allows
reducing both horizontal and vertical space simultaneously; : requires
trading off one for the other.  Either:

call/cc : lambda (return)
          blah ... return(42) blah ...


  lambda (return)
    blah ... return(42) blah ...

Collecting list's primary raison d'etres is for Scheme R6RS library /
R7RS define-library, and is overloaded to give double brackets for
let.  I don't see : displacing <* *> either, at least in the
define-library department.

GROUP/SPLIT has a "SPLIT" behavior that is not addressed by :.

So it seems that : can do many of the things that SUBLIST GROUP/SPLIT
and COLLECTINGLIST can do, but each has a domain that : cannot access.

> There is required stuff: double brackets and continuing the parameter list.
> Let’s see how many of the general usecases we can fit by just using the
> solutions to those. They must be there anyway, so generalizing them does not
> have a (high) cost. It might actually make the code easier to understand
> (and that way reduce the cost for the syntax), because the symbols then
> always have a fixed meaning.

You forgot the define-library thing.

> Additionally there is syntactic sugar which optimizes some rough edges. That
> isn’t required and adds overhead for those who want to learn the language.
> So I think it should be kept at a minimum: Keep in mind that every
> additional syntax-element has a price, so its benefit has to be higher than
> that price to merit an addition.


> Best wishes,
> Arne
> --
> A man in the streets faces a knife.
> Two policemen are there it once. They raise a sign:
>     “Illegal Scene! Noone may watch this!”
> The man gets robbed and stabbed and bleeds to death.
> The police had to hold the sign.
> …Welcome to Europe, citizen. Censorship is beautiful.
>    ( http://draketo.de/stichwort/censorship )

Free Next-Gen Firewall Hardware Offer
Buy your Sophos next-gen firewall before the end March 2013 
and get the hardware for free! Learn more.
Readable-discuss mailing list

Reply via email to