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

my $x->{foo} doesn't work

0 views
Skip to first unread message

tet...@tokyoprogrammer.com

unread,
May 20, 2004, 11:44:30 PM5/20/04
to perl5-...@perl.org
Hi all,

I love my variable and am looking for various ways of using it.
I will show you a bit of code.

$ perl -e 'my $x;$x->{foo}' # OK
$ perl -e '(my $x)->{foo}' # NG

I expected that autovivification would be applied to the
variable in the later case as well as in the first case, but
the results were different.
Therefore I wrote the following patch.
I would like your responses to that.

--- pp_hot.c.orig 2004-05-21 10:49:37.000000000 +0900
+++ pp_hot.c 2004-05-21 10:50:32.000000000 +0900
@@ -202,13 +202,13 @@
dSP; dTARGET;
XPUSHs(TARG);
if (PL_op->op_flags & OPf_MOD) {
- if (PL_op->op_private & OPpLVAL_INTRO)
- SAVECLEARSV(PAD_SVl(PL_op->op_targ));
- else if (PL_op->op_private & OPpDEREF) {
+ if (PL_op->op_private & OPpDEREF) {
PUTBACK;
vivify_ref(PAD_SVl(PL_op->op_targ), PL_op->op_private & OPpDEREF);
SPAGAIN;
}
+ else if (PL_op->op_private & OPpLVAL_INTRO)
+ SAVECLEARSV(PAD_SVl(PL_op->op_targ));
}
RETURN;
}

regards

--
Shinya Hayakawa
haya...@livedoor.jp

Rafael Garcia-Suarez

unread,
May 21, 2004, 4:47:54 AM5/21/04
to perl5-...@perl.org
tet...@tokyoprogrammer.com wrote:
>
> I love my variable and am looking for various ways of using it.
> I will show you a bit of code.
>
> $ perl -e 'my $x;$x->{foo}' # OK
> $ perl -e '(my $x)->{foo}' # NG
>
> I expected that autovivification would be applied to the
> variable in the later case as well as in the first case, but
> the results were different.

If you look at what contexts permit and forbid autovivification, you'll
see that the situation in perl is currently complex and probably not
very consistent. Anyway, in general lvalue contexts don't permit it; a
lexical declaration can be seen as this; and you still can write, in a
rather obfuscated way,

(my $x = {}) -> {foo}

Your patch looks correct at a first glance, but I'm not very inclined to
apply it, unless the crowd comes up with good reasons why to.

Dave Mitchell

unread,
May 21, 2004, 5:29:10 AM5/21/04
to Rafael Garcia-Suarez, perl5-...@perl.org
On Fri, May 21, 2004 at 10:47:54AM +0200, Rafael Garcia-Suarez wrote:
> Your patch looks correct at a first glance, but I'm not very inclined to
> apply it, unless the crowd comes up with good reasons why to.

The patch incorrectly removes introduction:

for (1..4) {
(my $x)->{foo} = 1;
print "$_: already exists!!\n" if exists $x->{bar};
$x->{bar} = 1;
}

with the patch outputs:

2: already exists!!
3: already exists!!
4: already exists!!


--
The Enterprise is captured by a vastly superior alien intelligence which
does not put them on trial.
-- Things That Never Happen in "Star Trek" #10

Rafael Garcia-Suarez

unread,
May 21, 2004, 5:35:05 AM5/21/04
to Dave Mitchell, perl5-...@perl.org
Dave Mitchell wrote:
> On Fri, May 21, 2004 at 10:47:54AM +0200, Rafael Garcia-Suarez wrote:
> > Your patch looks correct at a first glance, but I'm not very inclined to
> > apply it, unless the crowd comes up with good reasons why to.
>
> The patch incorrectly removes introduction:

I stand corrected, thanks!

Shinya Hayakawa

unread,
May 21, 2004, 6:09:32 AM5/21/04
to perl5-...@perl.org
Hi,

On Friday 21 May 2004 6:29 pm, Dave Mitchell wrote:
> The patch incorrectly removes introduction:
>
> for (1..4) {
> (my $x)->{foo} = 1;
> print "$_: already exists!!\n" if exists $x->{bar};
> $x->{bar} = 1;
> }
>
> with the patch outputs:
>
> 2: already exists!!
> 3: already exists!!
> 4: already exists!!

Thanks.
I rewrote the patch as follows.

--- pp_hot.c.orig 2004-05-21 10:49:37.000000000 +0900

+++ pp_hot.c 2004-05-21 18:43:46.000000000 +0900
@@ -204,7 +204,7 @@


if (PL_op->op_flags & OPf_MOD) {

if (PL_op->op_private & OPpLVAL_INTRO)

SAVECLEARSV(PAD_SVl(PL_op->op_targ));
- else if (PL_op->op_private & OPpDEREF) {
+ if (PL_op->op_private & OPpDEREF) {
PUTBACK;
vivify_ref(PAD_SVl(PL_op->op_targ), PL_op->op_private & OPpDEREF);
SPAGAIN;

--
Shinya Hayakawa
haya...@livedoor.jp

Dave Mitchell

unread,
May 21, 2004, 7:01:00 AM5/21/04
to Rafael Garcia-Suarez, perl5-...@perl.org
On Fri, May 21, 2004 at 10:47:54AM +0200, Rafael Garcia-Suarez wrote:
> tet...@tokyoprogrammer.com wrote:
> >
> > I love my variable and am looking for various ways of using it.
> > I will show you a bit of code.
> >
> > $ perl -e 'my $x;$x->{foo}' # OK
> > $ perl -e '(my $x)->{foo}' # NG
> >
> > I expected that autovivification would be applied to the
> > variable in the later case as well as in the first case, but
> > the results were different.
>
> If you look at what contexts permit and forbid autovivification, you'll
> see that the situation in perl is currently complex and probably not
> very consistent. Anyway, in general lvalue contexts don't permit it; a
> lexical declaration can be seen as this; and you still can write, in a
> rather obfuscated way,

Thinking about this some more; it could be argued that since op.c has already
gone to the trouble of marking the padsv op with the OPpDEREF flag, that
its a bug in pp_padsv for then ignoring that flag if it happens also to
be marked with OPpLVAL_INTRO. That is to say, ($x)->{foo} autovivifies
but (my $x)->{foo} doesn't. Clearly the OP's patch was wrong because it
threw out the baby with the bathwater, but maybe something like the
following (untested):


--- pp_hot.c Mon May 3 23:57:33 2004
+++ pp_hot.c+ Fri May 21 11:58:22 2004
@@ -205,7 +205,7 @@


if (PL_op->op_flags & OPf_MOD) {

if (PL_op->op_private & OPpLVAL_INTRO)

SAVECLEARSV(PAD_SVl(PL_op->op_targ));
- else if (PL_op->op_private & OPpDEREF) {
+ if (PL_op->op_private & OPpDEREF) {
PUTBACK;
vivify_ref(PAD_SVl(PL_op->op_targ), PL_op->op_private & OPpDEREF);
SPAGAIN;

--
"You're so sadly neglected, and often ignored.
A poor second to Belgium, When going abroad."
-- Monty Python - "Finland"

Rafael Garcia-Suarez

unread,
May 21, 2004, 7:03:24 AM5/21/04
to Dave Mitchell, perl5-...@perl.org
Dave Mitchell wrote:
>
> Thinking about this some more; it could be argued that since op.c has already
> gone to the trouble of marking the padsv op with the OPpDEREF flag, that
> its a bug in pp_padsv for then ignoring that flag if it happens also to
> be marked with OPpLVAL_INTRO. That is to say, ($x)->{foo} autovivifies
> but (my $x)->{foo} doesn't. Clearly the OP's patch was wrong because it
> threw out the baby with the bathwater, but maybe something like the
> following (untested):

which is the OP's second version :)
I still don't see why this would be a worthwhile language change. I've
no opinion on this in fact.

h...@crypt.org

unread,
May 21, 2004, 10:04:09 AM5/21/04
to Shinya Hayakawa, perl5-...@perl.org
Shinya Hayakawa <haya...@livedoor.jp> wrote:
:Thanks.

:I rewrote the patch as follows.
:
:--- pp_hot.c.orig 2004-05-21 10:49:37.000000000 +0900
:+++ pp_hot.c 2004-05-21 18:43:46.000000000 +0900
:@@ -204,7 +204,7 @@
: if (PL_op->op_flags & OPf_MOD) {
: if (PL_op->op_private & OPpLVAL_INTRO)
: SAVECLEARSV(PAD_SVl(PL_op->op_targ));
:- else if (PL_op->op_private & OPpDEREF) {
:+ if (PL_op->op_private & OPpDEREF) {
: PUTBACK;
: vivify_ref(PAD_SVl(PL_op->op_targ), PL_op->op_private & OPpDEREF);
: SPAGAIN;

I have nothing in principle against including this, except that it is
missing tests. Perhaps you could have a go at adding some tests to
explore the edge cases around this - a good starting point, for example,
would be to find a test case that exposes the problem with your first
attempt at this patch.

Hugo

Shinya Hayakawa

unread,
May 21, 2004, 10:09:28 AM5/21/04
to perl5-...@perl.org
Hi,

On Friday 21 May 2004 5:47 pm, Rafael Garcia-Suarez wrote:
> If you look at what contexts permit and forbid autovivification, you'll
> see that the situation in perl is currently complex and probably not
> very consistent. Anyway, in general lvalue contexts don't permit it; a
> lexical declaration can be seen as this;

The current Perl sourcecode may incorporate a mistake in OPpDEREF
what I did before(like OPpLVAL_INTRO).

> and you still can write, in a
> rather obfuscated way,
>
> (my $x = {}) -> {foo}

What you proposed is exactly what I have been doing but
there is nothing I can do apart from the above :-)

If this is successful I will rather prefer to write as follows:

++my $x->{foo} if cond();
...


--
Shinya Hayakawa
haya...@livedoor.jp

Elizabeth Mattijsen

unread,
May 21, 2004, 12:35:43 PM5/21/04
to Shinya Hayakawa, perl5-...@perl.org

my $x if cond()

is a Perl idiom that currently has an undefined behaviour. Unless
someone cleaned that up in the past weeks (while I was recovering
from a death in the family and a dead notebook).


Liz

Dan Kogai

unread,
May 21, 2004, 3:25:43 PM5/21/04
to perl5-...@perl.org
On May 21, 2004, at 17:47, Rafael Garcia-Suarez wrote:
> If you look at what contexts permit and forbid autovivification, you'll
> see that the situation in perl is currently complex and probably not
> very consistent. Anyway, in general lvalue contexts don't permit it; a
> lexical declaration can be seen as this; and you still can write, in a
> rather obfuscated way,
>
> (my $x = {}) -> {foo}
>
> Your patch looks correct at a first glance, but I'm not very inclined
> to
> apply it, unless the crowd comes up with good reasons why to.

Speaking of autovivification, how about such cases in reverse, That is,
when non-reference value is assigned with --, ++, +=, etc ? i.e.

perl -le '$x = {}; print ++$x'

You may expect '1' but this prints a random number, or numified version
of "HASH(0xdeadbeef)" plus 1. While this makes sense to those who
knows camel anatomy, this is somewhat asymmetrical and confusing....

[A few minutes later...]

Hey, watch this!

> % perl -le 'my $x=42; $x->[0]=3.14; print $x; print $x->[0]; print
> ref($x)'
> 42
> 3.14
>
> % perl -le 'my $x; $x->[0] = 3.14; print $x; print $x->[0]; print
> ref($x)'
> ARRAY(0x801180)
> 3.14
> ARRAY

See the difference? The first one has 42 assigned a priori. I have
duplicated this even on good old 5.00503, not to mention 5.8.4.

Dan the Camel (?:Ab)user

P.S. I found more of Hawakawa-kun's my abuses at

http://shibuya.pm.org/slides/bkcon2004/hayakawa.pdf

I only hope you don't do that in your PRODUCTION CODES....

Ronald J Kimball

unread,
May 21, 2004, 3:36:42 PM5/21/04
to Dan Kogai, perl5-...@perl.org
On Sat, May 22, 2004 at 04:25:43AM +0900, Dan Kogai wrote:

> Hey, watch this!
>
> >% perl -le 'my $x=42; $x->[0]=3.14; print $x; print $x->[0]; print
> >ref($x)'
> >42
> >3.14
> >
> >% perl -le 'my $x; $x->[0] = 3.14; print $x; print $x->[0]; print
> >ref($x)'
> >ARRAY(0x801180)
> >3.14
> >ARRAY
>
> See the difference? The first one has 42 assigned a priori. I have
> duplicated this even on good old 5.00503, not to mention 5.8.4.
>

Maybe you should try that again with use strict.

Ronald

Dan Kogai

unread,
May 21, 2004, 4:09:31 PM5/21/04
to perl5-...@perl.org
On May 22, 2004, at 04:25, Dan Kogai wrote:
> Hey, watch this!
>
>> % perl -le 'my $x=42; $x->[0]=3.14; print $x; print $x->[0]; print
>> ref($x)'
>> 42
>> 3.14
>>
>> % perl -le 'my $x; $x->[0] = 3.14; print $x; print $x->[0]; print
>> ref($x)'
>> ARRAY(0x801180)
>> 3.14
>> ARRAY
>
> See the difference? The first one has 42 assigned a priori. I have
> duplicated this even on good old 5.00503, not to mention 5.8.4.

You can even nest....

> % perl -le 'my $x=42; $x->[0]=3.14; $x->[0][0]=6.022e23;' \
> -e 'print "$x, $x->[0], $x->[0][0]"'
> 42, 3.14, 6.022e+23

And Devel::Peek says as follows. Strangely ROK is nowhere to be seen.

> % perl -MDevel::Peek -le 'my $x=42; $x->[0]=3.14;
> $x->[0][0]=6.022e23;' \
> -e 'Dump $x;Dump $x->[0];Dump $x->[0][0]'
> SV = PVIV(0x801828) at 0x801234
> REFCNT = 1
> FLAGS = (PADBUSY,PADMY,IOK,POK,pIOK,pPOK)
> IV = 42
> PV = 0x401930 "42"\0
> CUR = 2
> LEN = 3
> SV = PVNV(0x811734) at 0x80a924
> REFCNT = 1
> FLAGS = (NOK,POK,pNOK,pPOK)
> IV = 3
> NV = 3.14
> PV = 0x405280 "3.14"\0
> CUR = 4
> LEN = 35
> SV = NV(0x80e814) at 0x80f12c
> REFCNT = 1
> FLAGS = (NOK,pNOK)
> NV = 6.022e+23

And Storable "respects" this undocumented feature....

> % perl -MStorable -le 'my $x=42; $x->[0]=3.14; $x->[0][0]=6.022e23;' \
> -e 'store \$x=>"x"; my $y = retrieve "x"; print "$$y, $$y->[0],
> $$y->[0][0]"'
> 42, 3.14, 6.022e+23

But this magic fades as you modify the value thereof....

> % perl -le 'my $x=42; $x->[0]=3.14; $x->[0][0]=6.022e23;' \
> -e '$x=0; print "$x, $x->[0], $x->[0][0]"'
> 0, ,

But when you assign the same initial value it persists.... Maybe thanks
to optimizer ?

> % perl -le 'my $x=42; $x->[0]=3.14; $x->[0][0]=6.022e23;' \
> -e '$x=0; print "$x, $x->[0], $x->[0][0]"'
> 42, 3.14, 6.022e+23
> % perl -le 'my $x=42; $x->[0]=3.14; $x->[0][0]=6.022e23;' \
> -e '$x+=0; print "$x, $x->[0], $x->[0][0]"'
> 42, 3.14, 6.022e+23
> % perl -le 'my $x=42; $x->[0]=3.14; $x->[0][0]=6.022e23;' \
> -e '$x=2*3*7; print "$x, $x->[0], $x->[0][0]"'
> 42, 3.14, 6.022e+23

Dan the Zombie Hunter

Ronald J Kimball

unread,
May 21, 2004, 4:26:12 PM5/21/04
to Dan Kogai, perl5-...@perl.org
On Sat, May 22, 2004 at 05:09:31AM +0900, Dan Kogai wrote:
> And Storable "respects" this undocumented feature....

Whoa, slow down there! You're missing the forest for the trees.

These are just simple symbolic references.

Ronald

Dan Kogai

unread,
May 21, 2004, 4:43:10 PM5/21/04
to perl5-...@perl.org

Yes, use strict 'refs' does trap this.

> % perl -Mstrict=refs -le 'my $x=42; $x->[0]=3.14; print "$x, $x->[0]"'
> Can't use string ("42") as an ARRAY ref while "strict refs" in use at
> -e line 1.

That does explain what perl is actually doing. They just turn into
symbolic references.

> % perl -le 'my $x=42; $x->[0]=3.14; print ${"42"}[0]'
> 3.14
> % perl -le 'my $x=42; $x->[0]=3.14; print "42"->[0]'
> 3.14

The latter form is really funny. In a way you can use this as a hidden
global scalar.

That's also why the following worked.

On May 22, 2004, at 05:09, Dan Kogai wrote:
> But when you assign the same initial value it persists.... Maybe
> thanks to optimizer ?
>
>> % perl -le 'my $x=42; $x->[0]=3.14; $x->[0][0]=6.022e23;' \
>> -e '$x=0; print "$x, $x->[0], $x->[0][0]"'
>> 42, 3.14, 6.022e+23
>> % perl -le 'my $x=42; $x->[0]=3.14; $x->[0][0]=6.022e23;' \
>> -e '$x+=0; print "$x, $x->[0], $x->[0][0]"'
>> 42, 3.14, 6.022e+23
>> % perl -le 'my $x=42; $x->[0]=3.14; $x->[0][0]=6.022e23;' \
>> -e '$x=2*3*7; print "$x, $x->[0], $x->[0][0]"'
>> 42, 3.14, 6.022e+23

Okay. I understand. I think I can go to bed now. But IMHO '->' groks
symbolic references is a bad idea since we already have ${"sym"}
notation already....

Dan the Symbolically Referenced Man

Shinya Hayakawa

unread,
May 24, 2004, 11:06:06 AM5/24/04
to perl5-...@perl.org
Hi,

On Friday 21 May 2004 11:04 pm, h...@crypt.org wrote:
> I have nothing in principle against including this, except that it is
> missing tests. Perhaps you could have a go at adding some tests to
> explore the edge cases around this - a good starting point, for example,
> would be to find a test case that exposes the problem with your first
> attempt at this patch.

I wrote the patch which includes the tests.
Thank you so much for your resposes to my
recent mail. Would please indicate me if there
were any mistakes.


--- pp_hot.c.orig 2004-05-21 10:49:37.000000000 +0900

+++ pp_hot.c 2004-05-24 21:20:41.000000000 +0900


@@ -204,7 +204,7 @@
if (PL_op->op_flags & OPf_MOD) {
if (PL_op->op_private & OPpLVAL_INTRO)
SAVECLEARSV(PAD_SVl(PL_op->op_targ));
- else if (PL_op->op_private & OPpDEREF) {
+ if (PL_op->op_private & OPpDEREF) {
PUTBACK;
vivify_ref(PAD_SVl(PL_op->op_targ), PL_op->op_private & OPpDEREF);
SPAGAIN;

--- t/op/my.t.orig 2004-05-24 20:27:08.000000000 +0900
+++ t/op/my.t 2004-05-25 00:01:53.000000000 +0900
@@ -2,7 +2,7 @@

# $RCSfile: my.t,v $

-print "1..31\n";
+print "1..32\n";

sub foo {
my($a, $b) = @_;
@@ -99,3 +99,12 @@
# Supposed to be copy-on-write via force_normal after a THINKFIRST check.
print "$full $fonts{nok}\n";
}
+
+sub foo3 {
+ ++my $x->{foo};
+ print "not " if defined $x->{bar};
+ ++$x->{bar};
+}
+eval { foo3(); foo3(); };
+print "not " if $@;
+print "ok 32\n";


--
Shinya Hayakawa
haya...@livedoor.jp

Dave Mitchell

unread,
May 30, 2004, 6:58:25 PM5/30/04
to Shinya Hayakawa, perl5-...@perl.org
On Tue, May 25, 2004 at 12:06:06AM +0900, Shinya Hayakawa wrote:
> Hi,
>
> On Friday 21 May 2004 11:04 pm, h...@crypt.org wrote:
> > I have nothing in principle against including this, except that it is
> > missing tests. Perhaps you could have a go at adding some tests to
> > explore the edge cases around this - a good starting point, for example,
> > would be to find a test case that exposes the problem with your first
> > attempt at this patch.
>
> I wrote the patch which includes the tests.
> Thank you so much for your resposes to my
> recent mail. Would please indicate me if there
> were any mistakes.

Thanks, applied to bleedperl as change #22874.

--
In the 70's we wore flares because we didn't know any better.
What possible excuse does the current generation have?

0 new messages