About a month ago, a thread here suggested that we change the meaning of the comma operator. Currently, in scalar context the expression foo(), bar() means "evaluate foo(), discard the result, then return the value of bar()". It was suggested that this be changed to return the 2-element array (foo(), bar()). Has Larry ruled on this yet?
By the way, even if we do make this change, I think that in void context the expression foo(), bar() should still simply evaluate its parameters in order for their side-effects. This would allow comma expressions to remain as-is in loop statements (formerly for statements), which is where most of them are found anyway. For instance loop (my ($x = 0, $y = 10); $x < $y; ++$x, --$y) {...}
Joe Gottman wrote: > About a month ago, a thread here suggested that we change the meaning > of the comma operator. Currently, in scalar context the expression > foo(), bar() > means "evaluate foo(), discard the result, then return the value of > bar()". > It was suggested that this be changed to return the 2-element array > (foo(), bar()). Has Larry ruled on this yet?
Not that I'm aware of. For the most part, the previous discussion was focusing on what to replace the comma with in the case of "discard all but the last result", and my impression was that any ruling on the change would likely be contingent on the presence or absence of a suitable replacement. That said,
> By the way, even if we do make this change, I think that in void > context the expression > foo(), bar() > should still simply evaluate its parameters in order for their side- > effects. This would allow comma expressions to remain as-is in loop > statements (formerly for statements), which is where most of them are > found anyway.
I do like this suggestion. In the majority of cases where I've used the comma operator, I've either enclosed the whole thing in parentheses to turn it into a list, or I've treated it as a sequence of operators where even the last result got discarded. I've rarely been interested in just the last result, and I wouldn't mind that functionality being provided by means of a C<last> function which evaluates the list parameters for their side effects and returns the value of the last list parameter.
On Tue, Jan 20, 2004 at 08:12:28PM -0800, Jonathan Lang wrote: : Joe Gottman wrote:
: > About a month ago, a thread here suggested that we change the meaning : > of the comma operator. Currently, in scalar context the expression : > foo(), bar() : > means "evaluate foo(), discard the result, then return the value of : > bar()". : > It was suggested that this be changed to return the 2-element array : > (foo(), bar()). Has Larry ruled on this yet? : : Not that I'm aware of. For the most part, the previous discussion was : focusing on what to replace the comma with in the case of "discard all but : the last result", and my impression was that any ruling on the change : would likely be contingent on the presence or absence of a suitable : replacement.
I'm a little frustrated because I feel like I've ruled on it several times, but it never seems to "stick". I guess that's because it was never ruled in an Apocalypse, just in email. But I'm sure I'm on the record somewhere saying that I think [-1] is sufficient to pick out the last element of a list. If nothing else, just a couple of days ago, but I'm sure I also said it more than once in ancient times.
: That said, : : > By the way, even if we do make this change, I think that in void : > context the expression : > foo(), bar() : > should still simply evaluate its parameters in order for their side- : > effects. This would allow comma expressions to remain as-is in loop : > statements (formerly for statements), which is where most of them are : > found anyway. : : I do like this suggestion. In the majority of cases where I've used the : comma operator, I've either enclosed the whole thing in parentheses to : turn it into a list, or I've treated it as a sequence of operators where : even the last result got discarded. I've rarely been interested in just : the last result, and I wouldn't mind that functionality being provided by : means of a C<last> function which evaluates the list parameters for their : side effects and returns the value of the last list parameter.
Well, a C<last> function (or method) would be redundant with [-1], though I'm not totally opposed to redundancy. ["You can say that again."]
----- Original Message ----- From: "Larry Wall" <la...@wall.org> To: "Perl6" <perl6-langu...@perl.org> Sent: Wednesday, January 21, 2004 2:51 PM Subject: [perl] Re: Comma Operator
> On Tue, Jan 20, 2004 at 08:12:28PM -0800, Jonathan Lang wrote: > : Joe Gottman wrote: > : > About a month ago, a thread here suggested that we change the meaning > : > of the comma operator. Currently, in scalar context the expression > : > foo(), bar() > : > means "evaluate foo(), discard the result, then return the value of > : > bar()". > : > It was suggested that this be changed to return the 2-element array > : > (foo(), bar()). Has Larry ruled on this yet? > : > : Not that I'm aware of. For the most part, the previous discussion was > : focusing on what to replace the comma with in the case of "discard all but > : the last result", and my impression was that any ruling on the change > : would likely be contingent on the presence or absence of a suitable > : replacement.
> I'm a little frustrated because I feel like I've ruled on it several > times, but it never seems to "stick". I guess that's because it was > never ruled in an Apocalypse, just in email. But I'm sure I'm on > the record somewhere saying that I think [-1] is sufficient to pick > out the last element of a list. If nothing else, just a couple of > days ago, but I'm sure I also said it more than once in ancient times.
Great, so $x = foo(), bar(); means the same thing as $x = ( foo(), bar() );
Is the optimizer going to be smart enough so that given the expression $x = (foo(), bar(), glarch())[-1];
Perl6 won't have to construct a three-element array just to return the last element?
On Wed, Jan 21, 2004 at 08:51:33PM -0500, Joe Gottman wrote:
: Great, so : $x = foo(), bar(); : means the same thing as : $x = ( foo(), bar() );
No, we haven't changed the relative precedence of assignment and comma. I've been tempted to, but I always come back to liking the parens for visual psychological purposes. Plus changing the precedence would break
: Is the optimizer going to be smart enough so that given the expression : $x = (foo(), bar(), glarch())[-1]; : : Perl6 won't have to construct a three-element array just to return the last : element?
It's interesting to me that you assume there would be a three element array there. If the ()[] works like it does in Perl 5, the stuff inside the parens is always evaluated in list context. Which means that foo(), bar(), and glarch() can any of them return 0 or more elements. There's no guarantee that the final value doesn't come from foo() or bar().
Now, in Perl 6, slices are distinguished from single subscripts only by the form of the subscript, not by any sigil. So we can know for a fact that [-1] is not a slice. But that doesn't mean we can necessarily assume that the list in parens wants to evaluate its args in scalar context. Maybe it does, and maybe it doesn't.
That doesn't mean that we have to put the C comma operator back in though. It might just mean that the default is wrong on ()[]. Suppose we say that
(foo(), bar(), glarch())[-1]
by default evaluates its arguments in scalar context. To get the Perl 5 behavior, you'd merely have to use a splat to put the list into list context:
(* foo(), bar(), glarch())[-1]
Then (...)[] would become the standard way of producing a list of things evaluated in scalar context. Alternately, if you don't like the splat list, you can always say
[foo(), bar(), glarch()][-1]
which does the same thing.
Given all that, I think we can say that, yes, the compiler can optimize foo() and bar() to know they're running in void context. I'd generalize that to say that any unselected element of a scalar list can be evaluated in a void context, whether the subscript is -1 or 0 or any constant slice.
> No, we haven't changed the relative precedence of assignment and comma. > I've been tempted to, but I always come back to liking the parens > for visual psychological purposes.
Why does the psychology not apply to junctions? We have:
How about letting the Comma Operator share the transformation of the Ternary? Thus using ',' as the list constructor with apropriate precedence and ',,' as C-comma:
Larry Wall writes: > On Wed, Jan 21, 2004 at 08:51:33PM -0500, Joe Gottman wrote:
> : Great, so > : $x = foo(), bar(); > : means the same thing as > : $x = ( foo(), bar() );
> No, we haven't changed the relative precedence of assignment and > comma. I've been tempted to, but I always come back to liking the > parens for visual psychological purposes.
But that does lead to propagating the myth that parens, rather than commas, denote lists.
I think that matters less -- assigning lists is a much more common operation that using a C-style C<for> loop, and is also something that's a common source of errors with beginning Perl 5 programmers. Most of the C-style C<for> loops I see are unnecessary anyway:
* The majority of them are iterating through array indices (which are then only used to look up elements in those arrays), something far more easily achived with a C<foreach> loop and letting Perl take care of the indices.
* Many of the remainder are still iterating through consecutive integers, where C<for my $i (1 .. 10)> or whatever would much tidier than checking the boundary and increasing the iterator manually.
* Even for situations which 'genuinely' need the C-style loop in Perl 5 (such as looping through items in an array but also having the index number available) many of those in Perl 6 can use C<zip>.
So I think it's odd to optimize for convenience of a construct that has so little use.
Especially when there are ways of writing that statement without any commas in it:
While on the topic of C<loop> and parens, it hadn't occurred to me that the former could now be written without the latter; I knew that C<for>, C<if>, and C<while> could be, and now I look at it I can see that C<loop> can be so-written unambiguously -- but having 'internal', unbracketed, unquoted, unprotected semicolons scares me a little.
I'd feel more at ease if on seeing something like:
loop $i = $j = 0;
I could be certain that that semicolon denoted the end of that statement, without my having to know what C<loop> does.
Again, given how infrequently C<loop> is likely to be used, would imposing such a rule be much of a hardship? So a loop could look something like: