Front page | perl.perl5.porters |
Postings from May 2008
Re: [perl #51408] prototypes sneakily break :lvalue subs
Thread Previous
From:
Rafael Garcia-Suarez
Date:
May 28, 2008 01:34
Subject:
Re: [perl #51408] prototypes sneakily break :lvalue subs
Message ID:
b77c1dce0805280134h3a201e1fj7d34b2e8a48577be@mail.gmail.com
2008/3/4 via RT l. mai @ web. de <perlbug-followup@perl.org>:
> My real problem is related to lvalue subroutines and prototypes.
> Consider the following code:
>
> sub f :lvalue { $_ }
>
> With this, I'd expect to be able to use f() anywhere I can use $_,
> modulo weird things like indirect object syntax. But code like ...
>
> my $ref = \f();
> $$ref = 1;
>
> ... works and sets $_ to 1. Let's combine this with pass-by-alias:
>
> sub f :lvalue { $_ }
> sub g { $_[0] = 1 }
> g(f());
>
> This code binds g's $_[0] to $_ and sets $_ to 1, as expected.
> However:
>
> sub f :lvalue { $_ }
> sub g ($) { $_[0] = 1 }
> g(f());
>
> This code does nothing. The ($) prototype on g causes $_ to be
> passed by (temporary) value, and (per our initial observation)
> this kind of thing silently fails. g($_) works as expected, though,
> so there's something weird going on.
> Apparently the perl compiler simply inserts scalar()s in calls to
> g. This works fine for simple variables but breaks lvalue subs.
It doesn't insert scalar() calls, but indeed calls f in scalar context
(instead of list context as in the unprototyped case).
$ diff -u <(bleadperl -MO=Concise -e 'sub g;g(f())' 2>&1) <(bleadperl
-MO=Concise -e 'sub g($);g(f())' 2>&1)
--- /dev/fd/63 2008-05-28 10:26:06.651464655 +0200
+++ /dev/fd/62 2008-05-28 10:26:06.653628112 +0200
@@ -5,8 +5,8 @@
8 <1> entersub[t2] vKS/TARG,1 ->9
- <1> ex-list K ->8
3 <0> pushmark s ->4
-6 <1> entersub[t1] lKMS/NO(),TARG,INARGS,1 ->7
-- <1> ex-list lK ->6
+6 <1> entersub[t1] sKMS/NO(),TARG,INARGS,1 ->7
+- <1> ex-list sK ->6
4 <0> pushmark s ->5
- <1> ex-rv2cv sK ->-
5 <$> gv(*f) s/EARLYCV ->6
However, lvalue subs work in some scalar contexts:
$ bleadperl -MO=Concise -E 'sub f:lvalue{$x};$y=(f()=2);say$x'
e <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 47 -e:1) v:%,{ ->3
9 <2> sassign vKS/2 ->a
7 <2> sassign sKPS/2 ->8
3 <$> const(IV 2) s ->4
6 <1> entersub[t1] sKRMS*/NO(),TARG,1 ->7
- <1> ex-list sK ->6
4 <0> pushmark s ->5
- <1> ex-rv2cv sK ->-
5 <$> gv(*f) s ->6
- <1> ex-rv2sv sKRM*/1 ->9
8 <$> gvsv(*y) s ->9
a <;> nextstate(main 47 -e:1) v:%,{ ->b
d <@> say vK ->e
b <0> pushmark s ->c
- <1> ex-rv2sv sK/1 ->d
c <$> gvsv(*x) s ->d
-e syntax OK
$ bleadperl -E 'sub f:lvalue{$x};$y=(f()=2);say$x'
2
I wonder if it's a simple question of fiddling with the entersub flags.
Thread Previous