In a different thread, Buddha Buck wrote the following code snippet:

        for @a; @b -> $x is rw; $y { $x = $y[5] };

And I finally had to whimper publicly about this.

I've been lurking around the P6 process since the very beginning of the
RFC process.  I saw the new 'for' syntax come out, and I've watched it get
used by lots of people on this list.  My first reaction to it was "that's
counterintuitive and scary, and I don't like it".  But, that was my
reaction to a lot of the new Perl syntax, and I found that if I just sat
back and pondered it for a bit, I would soon come to realize that the new
syntax was fine, just different--and usually an improvement.

I have honestly tried to have the same sort of reconciliaton with the new
'for' syntax, and I just can't.  It's possible that I still just don't
understand it (I'm not sure I do), but I really believe that this syntax
is a Bad Thing and is going to cause a lot of bugs. I have the following
problems with it:

        for @a; @b -> $x is rw; $y { $x = $y[5] };

        1) This is (AFAIK) the ONLY place in Perl where a semicolon that
is not enclosed in parens is used for anything other than "end of
statement" (semi is used to separate parts of a perl5 C-style for loop
control statement, but that's in parens, so there is an indication that
the statement isn't over yet).

        2) The fact that the $x and $y variables are, by default,
read-only is (again, IMO) bad.  Perl's design philosophy has always been
"by default, all the freedom (and risk) that's available; if you want less
let me know".  Therefore, by default, these variables should be rw, and
you should be able to ask to have them const.

        3) Following that same idea, "is rw" is poor Huffman encoding
for something I'm likely to want fairly often.  Could we at least come up
with a single character equivalent?  Perhaps something like this:
                @a -> $x<       # rw ("$x can be an lvalue")
                @a -> $x>       # r  ("$x can be only be an rvalue")

        Either of these could be the default. Of course, what I'd really
like to see is:
                @a -> $x        # rw (default)
                @a -> $x<       # rw (explicitly stated)
                @a -> $x>       # r  ("$x can only be an rvalue")

        I believe the parser should be able to separate '<' used to mean
"can be an lval" from '<' used to mean "less than"...after all, you would
never alias elements in an array to a _value_ (which is what is returned
by $x < $y)...you would only alias elements to a variable.  If I'm wrong,
please correct me.  If it's going to be a problem, we could clarify it by
putting the bracket to the left of the variable, but then there is some
visual confusion with the head of the arrow operator.

        3) While it's really convenient to be able to loop over multiple
arrays and have each one alias to a separate variable, right now the
connection between the array and its alias variable is tenuous at
best...you don't know that $b is aliased until you read down the entire
statement (passing over a semicolon in the way that makes it look like
things have ended).  We explicitly moved regex modifiers to the front to
make them more visually distinct and easier to parse; shouldn't we
consider something similar here?

        4) Finally, and related to #3, the current syntax makes it look as
though $x is being pulled out of @b, when in fact it is being pulled out
of @a.



        I'm not a language designer and, usually, when I try to suggest
things I end up not seeing problems that they will cause with parsing.
However, just so this post does not consist entirely of negativism, I will
try to come up with a workable alternate syntax:

Current:        for @a; @b -> $x is rw, $y; $z { ...stuff... };

The above (IIUC) means "loop over @a, pulling out two elements at a time
and aliasing them to $x (which is rw) and $y (which is r).
Simultaneously loop over @b, aliasing its elements to $z (which is r)."

Suggested:      for @a -> $x, $y> __ @b -> $z> { ...stuff... };

The above means the same thing, but instead of specifying that $x is rw,
we have specified that $y and $z are r.


        At the bottom of this email are a bunch of other options, but the
one above is the one that I like best.  My reasons are as follows:

        1) Larry seems to have put a strong premium on not needing parens,
so I set that as an absolute requirement.

        2) Although having all the streams on the left is very convenient,
I judged it more important to be clear about which stremas were
aliasing to which variable(s).

        3) The new operator that I am proposing ("__") serves two
purposes:  for the human, it introduces a visual break which draws the eye
and makes you notice that there is another stream there, and for the
machine it says "ok, we're done with the list of variables being aliased
from @a...here's the next stream".  I propose calling it the "bridge"
operator, because you use it to cross one stream in order to get to the
next.  I deliberately made it a digraph, because (1) it provides a better
visual break that way and (2) it leaves the single character '_' operator
available for some less specialized purpose.  (Although, if anyone
wants to suggest a more generalized use for it, I'd love to see
it.)  Because underscore is a legal character in an identifier, there will
need to be whitespace between the bridge and the variable immediately
before it.  I tried some alternatives, but didn't like any of them as
well.

Here are the other suggestions I can up with:


                for @a -> $x<; @b -> $y { $x = $y[5] };
                for @a : $x< __ @b : $y { $x = $y[5] };
                for @a ~> $x< __ @b ~> $y { $x = $y[5] };
                for @a )~ $x<, $z __ @b )~ $y { $x = $y[5] };
                for @a _ @b __ $x<, $z _ $y { $x = $y[5] };
                for @a _ @b )~ $x<, $z _ $y { $x = $y[5] };
                for @a _ @b ]~ <$x, $z _ $y { $x = $y[5] };

        There were actually a bunch of others, but they were even less
satisfying.


        What do you all think?  Any value here?


--Dks



Reply via email to