develooper Front page | perl.perl5.porters | Postings from January 2009

Re: Context of early elements of list in scalar context

Thread Previous
From:
Nicholas Clark
Date:
January 11, 2009 15:05
Subject:
Re: Context of early elements of list in scalar context
Message ID:
20090111230518.GJ2919@plum.flirble.org
On Sun, Jan 11, 2009 at 04:58:00PM -0500, Eric Brine wrote:
> Is there a reason for the following difference in behaviour?
> 
> use strict;
> use warnings;
> 
> sub f {
>    if ( wantarray() ) {
>       print "list\n";
>    }
>    elsif ( defined wantarray() ) {
>       print "scalar\n";
>    }
>    else {
>       print "void\n";
>    }
> }
> 
> my $x =     ( f(), f(), f() );      print("\n");  # v,v,s
> my $y = sub { f(), f(), f() }->();  print("\n");  # s,s,s
> 
> (Perl 5.6.0, 5.6.1, 5.8.0, 5.8.8, 5.10.0)

Curious. No, I don't know why it does this. It doesn't seem right. It's not
to do with extra () meaning list context, because if I rewrite your example as

use strict;
use warnings;

sub f {
   if ( wantarray() ) {
      print "list\n";
   }
   elsif ( defined wantarray() ) {
      print "scalar\n";
   }
   else {
      print "void\n";
   }
   2;
}

sub g { ( f(), f(), f() ) }

my $x = ( f(), f(), f() );      print("$x\n");  # v,v,s
__END__

I still see the same:

$ perl ~/test/void 
void
void
scalar
2
scalar
scalar
scalar
2


So, something fishy is going on in g(). If I understand the output of Concise
correctly, it's reporting that none of the three subroutines' contexts are
known at compile time:

$ perl -MO=Concise,g ~/test/void
main::g:
d  <1> leavesub[1 ref] K/REFC,1 ->(end)
-     <@> lineseq KP ->d
1        <;> nextstate(main 8 void:17) v/2 ->2
c        <@> list KP ->d
2           <0> pushmark s ->3
5           <1> entersub[t1] KS/TARG,3 ->6
-              <1> ex-list K ->5
3                 <0> pushmark s ->4
-                 <1> ex-rv2cv sK/3 ->-
4                    <$> gv(*f) s ->5
8           <1> entersub[t2] KS/TARG,3 ->9
-              <1> ex-list K ->8
6                 <0> pushmark s ->7
-                 <1> ex-rv2cv sK/3 ->-
7                    <$> gv(*f) s ->8
b           <1> entersub[t3] KS/TARG,3 ->c
-              <1> ex-list K ->b
9                 <0> pushmark s ->a
-                 <1> ex-rv2cv sK/3 ->-
a                    <$> gv(*f) s ->b


(all are flagged as KS/TARG) whereas in the the longer output for main, the
first two are flagged as vKS/TARG (known void context) and only the third is
sKS/TARG (known scalar context):

$ perl -MO=Concise ~/test/void 
y  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 9 void:19) v/2 ->3
f     <2> sassign vKS/2 ->g
d        <@> list sKP ->e
3           <0> pushmark v ->4
6           <1> entersub[t2] vKS/TARG,3 ->7
-              <1> ex-list K ->6
4                 <0> pushmark s ->5
-                 <1> ex-rv2cv sK/3 ->-
5                    <$> gv(*f) s ->6
9           <1> entersub[t3] vKS/TARG,3 ->a
-              <1> ex-list K ->9
7                 <0> pushmark s ->8
-                 <1> ex-rv2cv sK/3 ->-
8                    <$> gv(*f) s ->9
c           <1> entersub[t4] sKS/TARG,3 ->d
-              <1> ex-list sK ->c
a                 <0> pushmark s ->b
-                 <1> ex-rv2cv sK/3 ->-
b                    <$> gv(*f) s ->c
e        <0> padsv[$x:9,11] sRM*/LVINTRO ->f
g     <;> nextstate(main 10 void:19) v/2 ->h
l     <@> print vK ->m
h        <0> pushmark s ->i
-        <1> ex-stringify sK/1 ->l
-           <0> ex-pushmark s ->i
k           <2> concat[t5] sK/2 ->l
i              <0> padsv[$x:9,11] s ->j
j              <$> const(PV "\n") s ->k
m     <;> nextstate(main 10 void:20) v/2 ->n
r     <2> sassign vKS/2 ->s
p        <1> entersub[t8] sKS/TARG,3 ->q
-           <1> ex-list sK ->p
n              <0> pushmark s ->o
-              <1> ex-rv2cv sK/3 ->-
o                 <$> gv(*g) s ->p
q        <0> padsv[$y:10,11] sRM*/LVINTRO ->r
s     <;> nextstate(main 11 void:20) v/2 ->t
x     <@> print vK ->y
t        <0> pushmark s ->u
-        <1> ex-stringify sK/1 ->x
-           <0> ex-pushmark s ->u
w           <2> concat[t9] sK/2 ->x
u              <0> padsv[$y:10,11] s ->v
v              <$> const(PV "\n") s ->w



But I don't know for sure why this happens, or what the right answer is.
But it doesn't feel consistent that 

sub g { ( f(), f(), f() ) }

results in all three being called in scalar context. Either all three are in
list context, or the first two are void and the third is scalar.

Nicholas Clark

Thread Previous


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About