According to Perldoc( https://perldoc.perl.org/perlop#Comma-Operator ):
Comma Operator
...
In list context, it's just the list argument separator, and inserts both its arguments into the list. These arguments are also evaluated from left to right.
In following code, I thought $n
should be 1
but it became 2
. What am I missing?
my $v = 1;
my $n = ( $v, $v = 2 )[0];
# I thought left "$v" would be evaluated (and return 1) first, then right "$v = 2" would.
say "n = $n"; # but output was 2
say "v = $v"; # 2
or
my $v = 1;
my @l = ( $v, $v = 2 );
say Dumper(\@l); # [ 2, 2 ], not [ 1, 2 ]
even when I changed the order:
my $v = 1;
# my $n = ( $v, $v = 2 )[0];
my $n = ( $v = 2, $v )[1];
say "n = $n"; # still 2
say "v = $v"; # 2
It does get evaluated left-to-right.
$ perl -MO=Concise,-exec -e'my $v = 1; my $n = ( $v, $v = 2 )[0];'
1 <0> enter v
2 <;> nextstate(main 1 -e:1) v:{
3 <$> const[IV 1] s \
4 <0> padsv[$v:1,3] sRM*/LVINTRO > my $v = 1;
5 <2> sassign vKS/2 /
6 <;> nextstate(main 2 -e:1) v:{
7 <0> pushmark s \ \
8 <$> const[IV 0] s | |
9 <0> pushmark s | |
a <0> padsv[$v:1,3] s $v > ( ... )[0] |
b <$> const[IV 2] s \ | > my $n = ...
c <0> padsv[$v:1,3] sRM* > $v = 2 | |
d <2> sassign sKS/2 / | |
e <2> lslice sK/2 / |
f <0> padsv[$n:2,3] sRM*/LVINTRO |
g <2> sassign vKS/2 /
h <@> leave[1 ref] vKP/REFC
-e syntax OK
The catch is that the scalar associated with $v
is placed on the stack, not the integer. You can see what's happening here:
use 5.014;
use warnings;
my @stack;
sub sassign {
my $rhs = pop(@stack);
my $lhs = pop(@stack);
$$rhs = $$lhs;
push @stack, $rhs;
}
# Stack $v $n
# ------- -- --
push @stack, \1; # 1
push @stack, \my $v; # 1,$v !d
sassign(); # $v 1
@stack = (); # 1
push @stack, \$v; # $v 1
push @stack, \2; # $v,2 1
push @stack, \$v; # $v,2,$v 1
sassign(); # $v,$v 2
pop(@stack); # $v 2 # Net result of slice.
push @stack, \my $n; # $v,$n 2 !d
sassign(); # $n 2 2
@stack = (); # 2 2
say $n; # 2
If you prefer aliases over references:
use 5.014;
use warnings;
use experimental qw( refaliasing declared_refs );
my @stack;
sub sassign {
my \$rhs = \pop(@stack);
my \$lhs = \pop(@stack);
$rhs = $lhs;
\$stack[@stack] = \$rhs;
}
# Stack $v $n
# ------- -- --
\$stack[@stack] = \1; # 1
\$stack[@stack] = \my $v; # 1,$v !d
sassign(); # $v 1
@stack = (); # 1
\$stack[@stack] = \$v; # $v 1
\$stack[@stack] = \2; # $v,2 1
\$stack[@stack] = \$v; # $v,2,$v 1
sassign(); # $v,$v 2
pop(@stack); # $v 2 # Net result of slice.
\$stack[@stack] = \my $n; # $v,$n 2 !d
sassign(); # $n 2 2
@stack = (); # 2 2
say $n; # 2
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With