Mailing List Archive

$_ in a a comma-op expression
$_ does not seem to be evaluated, or at least the result not saved, by
the comma operator:

perl -E '$_=100; @a=($_, do{$_=200}); say "@a";'
200 200

Is this a bug?
Re: $_ in a a comma-op expression [ In reply to ]
On Thu, Jan 18, 2024 at 06:55:24PM -0800, Jim Avera wrote:
> $_ does not seem to be evaluated, or at least the result not saved, by the
> comma operator:
>
> perl -E '$_=100; @a=($_, do{$_=200}); say "@a";'
> 200 200
>
> Is this a bug?

This isn't specific to $_:

$ perl -E 'my $x = 100; @a = ( $x, do { $x = 200 } ); say "@a"'
200 200
$ perl -E 'my @x = 100; @a = ( @x, do { $x[0] = 200 } ); say "@a"'
200 200
# be careful with aggregates though, -DPERL_RC_STACK in blead should fix this:
$ perl -E 'my @x = 100; @a = ( @x, do { @x = 200 } ); say "@a"'
semi-panic: attempt to dup freed string at -e line 1.
200

When building a list with a variable, perl pushes the SV for the
variable on the stack, not a copy, so in these cases the modification
to the variable is reflected in the final list.

Tony
Re: $_ in a a comma-op expression [ In reply to ]
On 19.01.24 03:55, Jim Avera wrote:
> $_ does not seem to be evaluated, or at least the result not saved, by
> the comma operator:
>
> perl -E '$_=100; @a=($_, do{$_=200}); say "@a";'
> 200 200
>
> Is this a bug?

I'm not 100% sure, but I would guess that variables are put into lists
as-is. That is, the semantics of ($x, $y) are not "get value of $x; add
it to list; get value of $y; add it to list", but instead "add $x to
list; add $y to list".

The reason why I think so is the existence of list assignment and \
referencing. For '($x, $y) = (1, 2)' to work, the list on the left-hand
side must contain the actual variables, not just their values.
Similarly, '\($x, $y)' produces a list of references (like '(\$x,
\$y)'), which would be impossible if variables had already been
evaluated to their values.

In your example, $_ is added to the list (as an unevaluated
variable/lvalue), then $_ is modified. It is only at the end, when the
list is used as an rvalue and copied to @a, that the list elements are
fully evaluated.

PS: Nothing to do with $_ specifically:
$ perl -wE 'my ($x, $y); say for $x, $y, $x, do { $x = "x"; $y = "y"; 42 }'
x
y
x
42
Re: $_ in a a comma-op expression [ In reply to ]
On Fri, 19 Jan 2024 at 03:55, Jim Avera <jim.avera@gmail.com> wrote:

> $_ does not seem to be evaluated, or at least the result not saved, by
> the comma operator:
>
> perl -E '$_=100; @a=($_, do{$_=200}); say "@a";'
> 200 200
>
> Is this a bug?
>

I think it is just undefined behavior. You cant combine a mutator and a
variable fetch in the same statment without the result being undefined. I
am pretty sura this is documented somewhere.

Yves



--
perl -Mre=debug -e "/just|another|perl|hacker/"
Re: $_ in a a comma-op expression [ In reply to ]
On Fri, 19 Jan 2024 at 13:09, demerphq <demerphq@gmail.com> wrote:

> On Fri, 19 Jan 2024 at 03:55, Jim Avera <jim.avera@gmail.com> wrote:
>
>> $_ does not seem to be evaluated, or at least the result not saved, by
>> the comma operator:
>>
>> perl -E '$_=100; @a=($_, do{$_=200}); say "@a";'
>> 200 200
>>
>> Is this a bug?
>>
>
> I think it is just undefined behavior. You cant combine a mutator and a
> variable fetch in the same statment without the result being undefined. I
> am pretty sura this is documented somewhere.
>
>
I think it is documented in perlop / auto-increment as well.

Personal todo: write examples of this undefined behaviour and look how it
is (un)defined in other major languages.


> Yves
>
>
>
> --
> perl -Mre=debug -e "/just|another|perl|hacker/"
>
Re: $_ in a a comma-op expression [ In reply to ]
On 19.01.24 13:08, demerphq wrote:
> On Fri, 19 Jan 2024 at 03:55, Jim Avera <jim.avera@gmail.com
> <mailto:jim.avera@gmail.com>> wrote:
>
> $_ does not seem to be evaluated, or at least the result not saved, by
> the comma operator:
>
> perl -E '$_=100; @a=($_, do{$_=200}); say "@a";'
> 200 200
>
> Is this a bug?
>
>
> I think it is just undefined behavior. You cant combine a mutator and a
> variable fetch in the same statment without the result being undefined.

Doesn't apply here. The comma operator ~~is a sequence point~~ is
documented as evaluating its operands from left to right.

https://perldoc.perl.org/perlop#Comma-Operator
Re: $_ in a a comma-op expression [ In reply to ]
On Fri, 19 Jan 2024 17:21:14 +0100
Lukas Mai <lukasmai.403+p5p@gmail.com> wrote:

> Doesn't apply here. The comma operator ~~is a sequence point~~ is
> documented as evaluating its operands from left to right.

Indeed, and furthermore the order of evaluation is perfectly well
defined. This is a problem with "naked variables" as SVs, not to do
with sequence points. It can be solved by operating on temporary
equivalent copies of the variables as new values.

Imagine if we knew for definite we were working with numbers, then we
could just do something like `$_+0` to take a numerical copy of it

$ perl -E '$_=100; @a = ($_+0, do{$_=200}); say "@a"'
100 200

Or if it's definitely strings we can `"$_"` it:

$ perl -E '$_="abc"; @a = ("$_", do{$_="def"}); say "@a"'
abc def


Annoyingly though there's no simple equivalent operator for making a
temporary copy of any arbitrary value, such as a reference.

$ perl -MData::Dump=pp -E \
'$_=[1,2,3]; @a = ($_, do{$_=[4,5,6]}); say pp(\@a)'
do {
my $a = [[4, 5, 6], 'fix'];
$a->[1] = $a->[0];
$a;
}

About the best you can write is a little `do` block, or some helper
function

$ perl -MData::Dump=pp -E \
'$_=[1,2,3]; @a = (do{my $tmp = $_}, do{$_=[4,5,6]}); say pp(\@a)'
[[1, 2, 3], [4, 5, 6]]

$ perl -MData::Dump=pp -E
'sub dup($x) { $x }
$_=[1,2,3]; @a = (dup($_), do{$_=[4,5,6]}); say pp(\@a)'
[[1, 2, 3], [4, 5, 6]]


--
Paul "LeoNerd" Evans

leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
Re: $_ in a a comma-op expression [ In reply to ]
on the other hand

$ perl -le '$x=10; @x=("$x", do{$x=20}); print "@x"'
10 20

$ perl -le '$x=10; @x=($x); push @x, do{$x=20}; print "@x"'
10 20

the right hand side all gets evaluated before the assignment happens.

On Thu, Jan 18, 2024 at 8:55?PM Jim Avera <jim.avera@gmail.com> wrote:

> $_ does not seem to be evaluated, or at least the result not saved, by
> the comma operator:
>
> perl -E '$_=100; @a=($_, do{$_=200}); say "@a";'
> 200 200
>
> Is this a bug?
>
>

--
"Lay off that whiskey, and let that cocaine be!" -- Johnny Cash
Re: $_ in a a comma-op expression [ In reply to ]
On 2024-01-19 03:55, Jim Avera wrote:
> $_ does not seem to be evaluated, or at least the result not saved, by
> the comma operator:
>
> perl -E '$_=100; @a=($_, do{$_=200}); say "@a";'
> 200 200
>
> Is this a bug?
>

Interesting.

perl -E '$_=100; @a=(+$_, do{$_=200}); say "@a";'
200 200

perl -E '$_=100; @a=(0+$_, do{$_=200}); say "@a";'
100 200

-- Ruud
Re: $_ in a a comma-op expression [ In reply to ]
0+ is special cased -- I bet if you added something else you'd get a result
instead of a pass-through

On Sat, Jan 20, 2024 at 4:17?AM Ruud H.G. van Tol via perl5-porters <
perl5-porters@perl.org> wrote:

>
> On 2024-01-19 03:55, Jim Avera wrote:
> > $_ does not seem to be evaluated, or at least the result not saved, by
> > the comma operator:
> >
> > perl -E '$_=100; @a=($_, do{$_=200}); say "@a";'
> > 200 200
> >
> > Is this a bug?
> >
>
> Interesting.
>
> perl -E '$_=100; @a=(+$_, do{$_=200}); say "@a";'
> 200 200
>
> perl -E '$_=100; @a=(0+$_, do{$_=200}); say "@a";'
> 100 200
>
> -- Ruud
>
>

--
"Lay off that whiskey, and let that cocaine be!" -- Johnny Cash
Re: $_ in a a comma-op expression [ In reply to ]
$ perl -E '$x=100; @a=($x,($x=200)); say "@a"'
200 200

Someone wondered if other languages behave similarly.   In Javascript
(at least as impl. in Firefox) a value seems to get copied to a
temporary before evaluating the next item in a comma-sep array assignment:

#!/bin/sh
path=$HOME/test.html  # can't be in /tmp if using snap :(
cat <<'EOD' >$path
<p id="demo"> </p>
<script>
  var x = 100;
  document.getElementById("demo").innerHTML = [x, (x=200)];
</script>
EOD
firefox $path  # shows 100,200
Re: $_ in a a comma-op expression [ In reply to ]
sorry, disregard

On Sat, Jan 20, 2024 at 3:59?PM David Nicol <davidnicol@gmail.com> wrote:

> 0+ is special cased -- I bet if you added something else you'd get a
> result instead of a pass-through
>
> On Sat, Jan 20, 2024 at 4:17?AM Ruud H.G. van Tol via perl5-porters <
> perl5-porters@perl.org> wrote:
>
>>
>> Interesting.
>>
>> perl -E '$_=100; @a=(+$_, do{$_=200}); say "@a";'
>> 200 200
>>
>> perl -E '$_=100; @a=(0+$_, do{$_=200}); say "@a";'
>> 100 200
>>
>