Larry is mostly out of touch this week, so working ourselves into a
fury over a potential design issue is probably a bit
counterproductive.
Perhaps someone can put together a statement of the problem and post
it, and we can leave the discussion for a bit, both to give larry
time to get his mail (probably not for a week) and to give everyone a
chance to mull over the issues?
--
Dan
--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
d...@sidhe.org have teddy bears and even
teddy bears get drunk
Square brackets are the only list constructor
=head1 VERSION
Maintainer: Luke Palmer <fibo...@babylonia.flatirons.org>
Date: 24 Sep 2002
Number: 362 (?)
Version: 1
=head1 ABSTRACT
This RFC responds to the fury on perl6-language about the redundancy of
parentheses and brackets with respect to list construction. It proposes
that only brackets may be used to create lists (or arrays), and
parentheses be left for grouping.
=head1 DESCRIPTION
Because of the addition of the flattening operator, parentheses in Perl 6,
when used as list constructors, are entirely redundant with brackets.
Additionally, parentheses have one inconsistency which brackets do not:
This is the following case, already shown on perl6-language:
$a = (); # $a is a list reference with 0 elements
$a = (10); # $a is the scalar 10
$a = (10, 20); # $a is a list reference with 2 elements
# ...
If the ability to construct lists with parentheses is removed, so is this
inconsistency. This has the added benefit that there is a significant
visual clue about when a list is being tossed around. This doesn't break
any convenience, just changes the look of it:
# Perl 6 # Perl 5
[$a, $b] ^= [$b, $a]; # ($a, $b) = ($b, $a)
print *[$a=$b],"\n"; # print(($a=$b), "\n");
push @a: *[1,2,3]; # push @a, (1,2,3);
push @a: [1,2,3]; # push @a, [1,2,3];
=head2 Subroutines
One place of quarrel is subroutine calls. Would this change the argument
list delimiters to brackets? I argue no, because they were never a
parenthesis-delimited list in the first place:
print("Hello, World", "\n");
print "Hello, World", "\n";
Thus, in this case, parentheses are used for grouping around the argument
list, not constructing it. The following transformation has been
mentioned:
print($a, $b);
is equivilent to
(print $a, $b);
so no change is necessary on account of subroutine calls.
=head2 Semantics
The semantics of brackets need to be changed slightly to support this.
Specifically, instead of creating a list I<reference>, they create a list
I<object>. This object may be stored in an @array interface, or a $scalar
interface. The $scalar interface works the same way as array references
did. But the way @arrays are assigned changes in this manner:
@array = [1, 2, 3]; # @array has 3 elements, not 1
@array = [[1, 2, 3]]; # @array has 1 element: an array object
@array[0] = [1, 2, 3]; # same thing
Slices work as they always have.
=head2 Hashes
For consistency, parentheses must be disallowed for hash construction as
well. The same semantic changes apply to braces. This fixes the common
mistake:
%hash = { a => 1, b => 2 };
will now DWIM.
=head1 IMPLEMENTATION
Very simple: Just a few changes in the grammar. Array references were
always references to objects in one sense, it's now just defined that way
on the surface.
Very good written text.
> =head1 DESCRIPTION
>
> Because of the addition of the flattening operator, parentheses in Perl 6,
> when used as list constructors, are entirely redundant with brackets.
> Additionally, parentheses have one inconsistency which brackets do not:
> This is the following case, already shown on perl6-language:
>
> $a = (); # $a is a list reference with 0 elements
> $a = (10); # $a is the scalar 10
> $a = (10, 20); # $a is a list reference with 2 elements
> # ...
>
> If the ability to construct lists with parentheses is removed, so is this
> inconsistency. This has the added benefit that there is a significant
> visual clue about when a list is being tossed around. This doesn't break
> any convenience, just changes the look of it:
>
> # Perl 6 # Perl 5
> [$a, $b] ^= [$b, $a]; # ($a, $b) = ($b, $a)
> print *[$a=$b],"\n"; # print(($a=$b), "\n");
> push @a: *[1,2,3]; # push @a, (1,2,3);
> push @a: [1,2,3]; # push @a, [1,2,3];
I didn't follow the Perl6 discussion very well,
so I have perhaps the advantage seeing all this with Perl5 eyes only.
Perhaps it's a good idea to add an explanation what is the most significant
benefit of this new notion. It's only said, that there is a significant
visual clue about when a list is being tossed around.
As I don't feel much that I don't know whether a variable is in list or scalar
context in Perl5, I'm asking whether there are some more (important) advantages.
Especially as there is an obviously disadvantage of the Perl6 syntax:
It's in all lines but the last one character longer :-))
As I'm sure that there is the chance of 1,2 or 3 short sentences explaining the
real advantages, I only wanted to ask for a completion of this nice text.
Greetings,
Janek
Luke, thanks and congratulations on a well written case. You put into
words exactly what I was trying to put into words myself. Now I don't have
to finish this ugly draft I have lying around.
-Miko
--------------------------------------------------------------------
mail2web - Check your email from the web at
http://mail2web.com/ .
I cringe every time someone says "Parens construct lists in Perl 6."
Parens don't construct lists in Perl 6. They merely group. The only
difference from Perl 5 is that if they happen to group a comma in
scalar context, the comma acts differently, not the parens. But the
comma acts differently whether or not there are parens. It depends
only on the context. I admit that it's difficult to get a comma into
scalar context without parens, at least with the current precedence
table. But if we swapped the precedence of comma and assignment,
it would still be the case that
$a = 1,2,3;
generates a list because of the comma. The grouping would be implicit.
(But there are other problems with doing that.)
You can actually do the grouping without parens:
$foo = do { 1,2,3 };
Gee, maybe we should get rid of parens, since they're redundant. :-)
So the parens have little to do with the list construction. It's all
the comma's fault.
And in general, parentheses should not be used to construct lists in
scalar context. It's better to use [] explicitly. In list context,
the [] is not at all the same as (), because () is essentially a
no-op in list context, while [] creates an array ref.
I suppose we could make comma merely puke in scalar context rather
than DWIM, at least optionally.
: Additionally, parentheses have one inconsistency which brackets do not:
: This is the following case, already shown on perl6-language:
:
: $a = (); # $a is a list reference with 0 elements
: $a = (10); # $a is the scalar 10
: $a = (10, 20); # $a is a list reference with 2 elements
: # ...
:
: If the ability to construct lists with parentheses is removed, so is this
: inconsistency.
I don't think that's an important inconsistency.
: This has the added benefit that there is a significant
: visual clue about when a list is being tossed around. This doesn't break
: any convenience, just changes the look of it:
:
: # Perl 6 # Perl 5
: [$a, $b] ^= [$b, $a]; # ($a, $b) = ($b, $a)
: print *[$a=$b],"\n"; # print(($a=$b), "\n");
: push @a: *[1,2,3]; # push @a, (1,2,3);
: push @a: [1,2,3]; # push @a, [1,2,3];
I'd rather they just work the way people expect from Perl 5. Requiring
people to say *[1,2,3] when they could say 1,2,3 is needless obfuscation.
: =head2 Subroutines
:
: One place of quarrel is subroutine calls. Would this change the argument
: list delimiters to brackets? I argue no, because they were never a
: parenthesis-delimited list in the first place:
:
: print("Hello, World", "\n");
: print "Hello, World", "\n";
:
: Thus, in this case, parentheses are used for grouping around the argument
: list, not constructing it.
Indeed. :-)
: The following transformation has been
: mentioned:
:
: print($a, $b);
:
: is equivilent to
:
: (print $a, $b);
:
: so no change is necessary on account of subroutine calls.
:
: =head2 Semantics
:
: The semantics of brackets need to be changed slightly to support this.
: Specifically, instead of creating a list I<reference>, they create a list
: I<object>. This object may be stored in an @array interface, or a $scalar
: interface. The $scalar interface works the same way as array references
: did. But the way @arrays are assigned changes in this manner:
:
: @array = [1, 2, 3]; # @array has 3 elements, not 1
: @array = [[1, 2, 3]]; # @array has 1 element: an array object
: @array[0] = [1, 2, 3]; # same thing
:
: Slices work as they always have.
I think if you're going to replace the whole array using a reference, it's
better to use the explicit binding:
@array := [1,2,3]
It's awfully handy that the right side of a normal list assignment
automatically flattens. And it's what Perl 5 programmers expect.
They certainly won't expect [] to flatten.
: =head2 Hashes
:
: For consistency, parentheses must be disallowed for hash construction as
: well. The same semantic changes apply to braces. This fixes the common
: mistake:
:
: %hash = { a => 1, b => 2 };
:
: will now DWIM.
Well, that one can be caught, if not the other one. Again, the right
approach to dealing with references is probably to bind:
%hash := { a => 1, b => 2 };
Larry
I rather like Perl 5's scalar comma operator.
> : $a = (); # $a is a list reference with 0 elements
> : $a = (10); # $a is the scalar 10
> : $a = (10, 20); # $a is a list reference with 2 elements
>
> I don't think that's an important inconsistency.
What if $a and $b are both array refs, and maintenance programmer
changes:
for $a, $b { print }
to:
for $a { print }
Will that end up iterating across @$a? The equivalent of that gotcha
was forever bugging me in Python (gack).
--
Chip Salzenberg - a.k.a. - <ch...@pobox.com>
"It furthers one to have somewhere to go."
[SNIP]
>
> : This has the added benefit that there is a significant
> : visual clue about when a list is being tossed around. This doesn't
> break
> : any convenience, just changes the look of it:
> :
> : # Perl 6 # Perl 5
> : [$a, $b] ^= [$b, $a]; # ($a, $b) = ($b, $a)
> : print *[$a=$b],"\n"; # print(($a=$b), "\n");
> : push @a: *[1,2,3]; # push @a, (1,2,3);
> : push @a: [1,2,3]; # push @a, [1,2,3];
>
> I'd rather they just work the way people expect from Perl 5. Requiring
> people to say *[1,2,3] when they could say 1,2,3 is needless
> obfuscation.
I think needless obfuscation is treating $a = (10); as a scalar instead
of a list reference containing one item when the rest of the the $a =
() are list references.
-Noah
I think needless obfuscation is treating $a = (10) differently than $a =
10. The latter is the behavior we've come to expect from other
languages.
This may not look consistent:
$a = (10);
$a = (10, 20);
$a = (10, 20, 30);
#...
But it is consistent with this:
$a = do { 10 };
$a = do { 10, 20 };
$a = do { 10, 20, 30 };
#...
(Thanks for pointing that out, Larry.)
Parens don't construct lists EVER! They only group elements
syntactically. One common use of parens is to surround a
comma-separated list, but the *commas* are creating the list, *not* the
parens!
--Brent Dax <bren...@cpan.org>
@roles=map {"Parrot $_"} qw(embedding regexen Configure)
Wire telegraph is a kind of a very, very long cat. You pull his tail in
New York and his head is meowing in Los Angeles. And radio operates
exactly the same way. The only difference is that there is no cat.
--Albert Einstein (explaining radio)
Wow, somehow you've convinced me that all the problems I saw before aren't
really there. Well, switch on the light, there's no monsters under the
bed afterall.
> : This has the added benefit that there is a significant
> : visual clue about when a list is being tossed around. This doesn't break
> : any convenience, just changes the look of it:
> :
> : # Perl 6 # Perl 5
> : [$a, $b] ^= [$b, $a]; # ($a, $b) = ($b, $a)
> : print *[$a=$b],"\n"; # print(($a=$b), "\n");
> : push @a: *[1,2,3]; # push @a, (1,2,3);
> : push @a: [1,2,3]; # push @a, [1,2,3];
>
> I'd rather they just work the way people expect from Perl 5. Requiring
> people to say *[1,2,3] when they could say 1,2,3 is needless obfuscation.
According to the RFC, they could say it either way. I suppose I should
have clarified that.
Well, fine, there goes my argument. I ended up happy, though.
Luke
> Parens don't construct lists EVER! They only group elements
> syntactically. One common use of parens is to surround a
> comma-separated list, but the *commas* are creating the list, *not* the
> parens!
>
Following this rule would mean that
$a = (); # $a is a list reference with 0 elements
should not be a list reference at all and would appear inconsistent.
-Noah
No, because there are zero commas. Squint and you can see them. :-)
Trey
> Parens don't construct lists in Perl 6. They merely group.
> The only difference from Perl 5 is that if they happen to group a
> comma in scalar context, the comma acts differently, not the parens.
Do parens still provide list context on the left side of an assignment?
What do these two do:
my $x = @ARGS;
my ($y) = @ARGS;
Parens just grouping suggests that C<$x> and C<$y> should be the same
(which may well be good, as it's a subtle distinction which trips up
many beginners in Perl 5). If so, what's the preferred way of getting
the 'other' behaviour?
Smylers
Maybe:?
my ($y) ^= @ARGS;
Luke
> > my $x = @ARGS;
> > my ($y) = @ARGS;
>
> Maybe:?
>
> my ($y) ^= @ARGS;
Or (presumably equivalently):
my $y ^= @ARGS;
But that's horrible. Presumably with two or more variables the comma
would denote list context, so the caret is only needed for exactly one
variable. That's an awkward special-case to have to introduce.
Though thinking about this more, it may not be too much of a problem. A
main use of this in Perl 5 is with C<@_>. Since Perl 6 will have named
sub params this will be much less common and may not be something to
worry about.
Smylers
>I cringe every time someone says "Parens construct lists in Perl 6."
>Parens don't construct lists in Perl 6.
>
>: Additionally, parentheses have one inconsistency which brackets do not:
>: This is the following case, already shown on perl6-language:
>:
>: $a = (); # $a is a list reference with 0 elements
>: $a = (10); # $a is the scalar 10
>: $a = (10, 20); # $a is a list reference with 2 elements
>: # ...
>:
>: If the ability to construct lists with parentheses is removed, so is this
>: inconsistency.
>
>I don't think that's an important inconsistency.
>
>
So is it even true that
$a = (); # is this really a list reference with 0 elements? Or is
this just undef? There is no comma...
--
Glenn
=====
Not everything that is counted counts,
and not everything that counts can be counted.
-- A. Einstein
That's like saying
$y = @ARGS[$_] for 0..+@ARGS;
so $y will probably end up with the _last_ element of @ARGS.
I suggest:
my $y = shift; # if this still works in perl6
my $y = @ARGS[0];
~ John Williams
Er, kind of. More precisely, use of parens on the left provides a
flattening list context on the right side, just as in Perl 5. I guess
I did not make clear that a basic Perl 6 design decision was that = will
appear to work exactly as it does in Perl 5, while all the new semantics
get put into := instead. In fact, = doesn't work exactly the same, because
it lazily evaluates things like ranges and other potentially infinite lists.
But that should be more or less transparent.
Larry
Most of the uses of which are actually in void context, where it
doesn't matter if we technically build a list and throw it away,
or throw away all but the last value, then throw that one away too.
Which is why it got decided the way it was. If you really want the
last value, you can always use
(LIST)[-1]
which could be construed as better documentation. Admittedly it's
not quite the same, since LIST is evaluated in list context.
Anyway, if we did outlaw comma in scalar context, it would not apply
to void context, or we couldn't write:
loop ($a=0, $b=1; $c; $a++, $b++) { ... }
: > : $a = (); # $a is a list reference with 0 elements
: > : $a = (10); # $a is the scalar 10
: > : $a = (10, 20); # $a is a list reference with 2 elements
: >
: > I don't think that's an important inconsistency.
:
: What if $a and $b are both array refs, and maintenance programmer
: changes:
: for $a, $b { print }
: to:
: for $a { print }
: Will that end up iterating across @$a? The equivalent of that gotcha
: was forever bugging me in Python (gack).
No, in list context reference scalars must still be explicitly
dereferenced. The $ on the front still means something occasionally.
It's only in scalar contexts that $ can be autodereffed as an array
now, so that someone can say
push $a, @list;
But if you say
push $a, $a;
you get the ref in $a pushed onto @$a, as it currently stands.
Larry
Actually, () has -1 commas, which is why it's not ambiguous. Rather,
it's ($x) that has zero commas, so it's naturally ambiguous, and thus
must depend on context to determine whether to produce a scalar or
a list value.
Seriously, () is just a special token. We could easily have used a
special token like NULLLIST instead. What does INTERCAL use?
Larry
I didn't realize you were distinguishing scalar from void in this, uh,
context. I agree that scalar comma is expendable if void comma can be
rescued. However:
> ... where it doesn't matter if we technically build a list and throw
> it away, or throw away all but the last value, then throw that one
> away too.
Except that it would impose list context on the values; and if the
values to be thrown away are no longer in void context, unnecessary
work may be done to evaluate them fully. This is a bad thing.
(Or are you rescinding the rule that void context is a special kind of
scalar context?)
> If you really want the last value, you can always use
> (LIST)[-1]
If scalar comma goes away, I'd be inclined to replace it with
do { E1; E2; E3 }
which evaluates E1 and E2 in void context.
PLEASE DO ;1 <- #0
(Hey, you asked.)
--
Mark REED | CNN Internet Technology
1 CNN Center Rm SW0831G | mark...@cnn.com
Atlanta, GA 30348 USA | +1 404 827 4754
--
It is not enough to have great qualities, we should also have the
management of them.
-- La Rochefoucauld