Discussion:
$_ in a a comma-op expression
(too old to reply)
Tony Cook
2024-01-19 03:14:48 UTC
Permalink
$_ does not seem to be evaluated, or at least the result not saved, by the
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
Paul "LeoNerd" Evans
2024-01-19 17:03:44 UTC
Permalink
On Fri, 19 Jan 2024 17:21:14 +0100
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.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
"Ruud H.G. van Tol" via perl5-porters
2024-01-20 10:17:08 UTC
Permalink
$_ does not seem to be evaluated, or at least the result not saved, by
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

Loading...