Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Re: &&= vivify keys?

by dada (Chaplain)
on Apr 18, 2012 at 09:49 UTC ( [id://965689]=note: print w/replies, xml ) Need Help??


in reply to &&= vivify keys?

while the explanation of Eliya++ pretty much solves the issue, I noticed a strange behaviour. if I do exactly the same but using a tied hash, Perl seems to parse the instruction differently. no key with undef value is created at all.

#!/usr/bin/env perl use 5.010; use warnings; use strict; use Tie::Hash; use Data::Dumper; package DEBUGHASH; use base 'Tie::Hash'; sub TIEHASH { my $self = bless {}, shift; warn "TIEHASH $self\n"; return $self; } sub STORE { my($self, $key, $val) = @_; warn "STORE $self $key=$val\n"; $self->{$key} = $val; } sub FETCH { my($self, $key) = @_; warn "FETCH $self $key\n"; return $self->{$key}; } sub EXISTS { my($self, $key) = @_; warn "EXISTS $self $key\n"; return exists $self->{$key}; } sub FIRSTKEY { my($self) = @_; warn "FIRSTKEY $self\n"; my $key = scalar keys %{$self}; return each %{$self}; } sub NEXTKEY { my($self, $lastkey) = @_; warn "NEXTKEY $self $lastkey\n"; return each %{$self}; } package main; my %x; tie %x, 'DEBUGHASH'; $x{a} &&= 1; # this one, instead, generates the 'a' => undef key # $x{a} = $x{a} && 1; say Dumper(\%x); # just to check that the hash really works... $x{b} = 42; say Dumper(\%x);

running the code above I get:

TIEHASH DEBUGHASH=HASH(0x649f78) FETCH DEBUGHASH=HASH(0x649f78) a FIRSTKEY DEBUGHASH=HASH(0x649f78) $VAR1 = {}; STORE DEBUGHASH=HASH(0x649f78) b=42 FIRSTKEY DEBUGHASH=HASH(0x649f78) FETCH DEBUGHASH=HASH(0x649f78) b NEXTKEY DEBUGHASH=HASH(0x649f78) b $VAR1 = { 'b' => 42 };

probably not worth further investigation, but curious nonetheless :-)

cheers,
Aldo

King of Laziness, Wizard of Impatience, Lord of Hubris

Replies are listed 'Best First'.
Re^2: &&= vivify keys?
by ikegami (Patriarch) on Apr 18, 2012 at 21:01 UTC

    It's because what Eliya said isn't completely true. «$x{a} &&= 1;» isn't exactly equivalent to «$x{a} = $x{a} && 1;». Specifically, «$x{a}» is never assigned to itself. What really happens:

    1. The RHS of the assignment (1) is evaluated.
    2. The LHS of the assignment ($x{a}) is evaluated in lvalue context (which vivifies the hash element). [FETCH]
    3. If the scalar from the LHS is false,
      1. The scalar from the RHS is assigned to the scalar returned by the LHS. [STORE]

    Notice how the store is conditional? The autovivification actually occurs on fetch.

    The reason your tie code doesn't behave like the non-tie code is that you didn't autovivify the inner hash on fetch like the non-tie code does (step 2). But that's excusable -- I don't know if you can even tell you were called in lvalue context.

      Thanks for the clarification.

      As for

      3. If the scalar from the LHS is false, ...

      I think that should be

          3. If the scalar from the LHS is true, ...

      How else could a true value in the scalar ever change?

      $ perl -E'$x=1; $x &&= 0; say $x' 0
Re^2: &&= vivify keys?
by sundialsvc4 (Abbot) on Apr 18, 2012 at 11:23 UTC

    It has been my experience that “tied hashes” don’t necessarily work as ordinary true hashes do.   I don’t profess to know the perlguts of it, and it seems to be somewhat implementation-dependent.

    My approach in any case would simply be to test whether the key exists or not, with an if-statement.   That should work in every case and at the same time be perfectly clear.

      I know it's many years late but I would like to know exactly in what ways you have noticed tied hashes acting differently.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://965689]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (4)
As of 2024-04-25 17:52 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found