Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Re: $_ in a a comma-op expression

1 view
Skip to first unread message

Tony Cook

unread,
Jan 18, 2024, 10:30:05 PMJan 18
to Jim Avera, perl5-...@perl.org
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

Paul "LeoNerd" Evans

unread,
Jan 19, 2024, 12:15:04 PMJan 19
to Lukas Mai, perl5-...@perl.org
On Fri, 19 Jan 2024 17:21:14 +0100
Lukas Mai <lukasmai...@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

leo...@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

unread,
Jan 20, 2024, 5:30:04 AMJan 20
to perl5-...@perl.org

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

0 new messages