Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

%+ and cloning

by PetaMem (Priest)
on Jan 11, 2010 at 11:01 UTC ( [id://816700]=perlquestion: print w/replies, xml ) Need Help??

PetaMem has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks, it seems, that %+ refuses regular attempts of cloning it:
#!/usr/bin/perl use strict; use warnings; use Storable qw(dclone); use Data::Dumper; my $str = "Rico"; $str =~ m{(?<name>ico)}xms; my $match = dclone \%+; print \%+,"\n"; print "match: $match\n", Dumper($match); $str =~ m{(?<buba>R)}xms; my $match2 = dclone \%+; print \%+,"\n"; print "match: $match\n", Dumper($match); print "match2: $match2\n", Dumper($match2);

edit:

output on my machine:

HASH(0x1c6fba0)
match:  HASH(0x1a20d48)
$VAR1 = {
          'name' => 'ico'
        };
HASH(0x1c6fba0)
match:  HASH(0x1a20d48)
$VAR1 = {
          'buba' => 'R'  # <- now this is unexpected
        };
match2: HASH(0x1a4baf0)
$VAR1 = {
          'buba' => 'R'
        };
In contrast, the following code works as expected:
my %test = ( hula => 1, ); my $testclone = dclone \%test; print "test: $testclone\n", Dumper($testclone); %test = ( different => 1, ); my $testclone2 = dclone \%test; print "test: $testclone\n", Dumper($testclone); print "test2: $testclone2\n", Dumper($testclone2);

What's going on here? The cloned hashref ($match) changes content although it has (and keeps) a different address.

$ perl -V Summary of my perl5 (revision 5 version 10 subversion 1) configuration +: Platform: osname=linux, osvers=2.6.30-tuxonice-r5, archname=x86_64-linux-thr +ead-multi uname='linux sol 2.6.30-tuxonice-r5 #1 smp preempt tue sep 1 15:41 +:45 cest 2009 x86_64 intel(r) core(tm)2 cpu t7200 @ 2.00ghz genuinein +tel gnulinux ' config_args='-des -Duseshrplib -Darchname=x86_64-linux-thread -Dcc +=x86_64-pc-linux-gnu-gcc -Doptimize=-march=core2 -O2 -pipe -Dscriptdi +r=/usr/bin -Dprefix=/usr -Dvendorprefix=/usr -Dsiteprefix=/usr -Dprivlib=/usr +/lib64/perl5/5.10.1 -Darchlib=/usr/lib64/perl5/5.10.1/x86_64-linux-th +read-multi -Dvendorlib=/usr/lib64/perl5/vendor_perl/5.10.1 -Dvendorarch=/usr/ +lib64/perl5/vendor_perl/5.10.1/x86_64-linux-thread-multi -Dsitelib=/usr/lib64/perl5/site_perl/5.10.1 -Dsitearch=/usr/lib64/ +perl5/site_perl/5.10.1/x86_64-linux-thread-multi -Dlibperl=libperl.so.5.10.1 -Dlocincpth= -Duselargefiles -Dd_semc +tl_semun -Dinc_version_list=5.10.0 5.10.0/x86_64-linux-thread-multi - +Dcf_by=Gentoo -Dmyhostname=localhost -Dperladmin=root@localhost -Dinstallusrbinperl=n -Ud_csh -Uusenm -Dusethreads -Ui_ndbm -Ui_gdb +m -Ui_db -Dusrinc=/usr/include -Dlibpth=/usr/local/lib64 /lib64 /usr/ +lib64' hint=recommended, useposix=true, d_sigaction=define useithreads=define, usemultiplicity=define useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=und +ef use64bitint=define, use64bitall=define, uselongdouble=undef usemymalloc=n, bincompat5005=undef

Bye
 PetaMem
    All Perl:   MT, NLP, NLU

Replies are listed 'Best First'.
Re: %+ and cloning
by BrowserUk (Patriarch) on Jan 11, 2010 at 12:03 UTC

    Try this version of your code that uses Data::Dump and things become obvious:

    #! perl -slw use strict; use warnings; use Storable qw(dclone); use Data::Dump qw[ pp ]; my $str = "Rico"; $str =~ m{(?<name>ico)}xms; my $match = dclone \%+; print \%+,; print " match: $match -", pp $match; $str =~ m{(?<buba>R)}xms; my $match2 = dclone \%+; print \%+; print " match: $match ", pp $match; print "match2: $match2 ", pp $match2; __END__ C:\test>816700 HASH(0x22ee20) match: HASH(0x6f218) -{ # tied Tie::Hash::NamedCapture } HASH(0x22ee20) match: HASH(0x6f218) { # tied Tie::Hash::NamedCapture } match2: HASH(0x6f128) { # tied Tie::Hash::NamedCapture }

    %+ is not a real hash, but rather a tied hash. And cloning it appears to simply gives you another tied reference to the same global internal data structure.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      Thanks for your insight.

      So I went back to twig technology and copied the hash via
      sub copy_hash { my $hr = shift // return {}; # get hash to copy or return empty ha +shref if not given my %copy = (); while (my ($k, $v) = each %{$hr}) { $copy{$k} = $v; } return \%copy; }

      Which works. So this is it? Best way to go?

      Bye
       PetaMem
          All Perl:   MT, NLP, NLU

        A simple my %copy = %+; is equivalent to your sub. However, that may not be enough!

        According to the docs for Tie::Hash::NamedCapture, the values of the tied hash can contain an array reference holding multiple captures due to the re-use of the same named capture. In which case you might need to use something more complex to perform a deep copy operation.

        That said, in my simple tests, this doesn't seem to apply to %+. It does apply to %- though.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
        That depends on ones definition of 'best'. One could also write:
        sub copy_hash { my $hr = shift // return {}; my $copy; @$copy{keys %$hr} = value %$hr; $copy; }
        or just:
        sub copy_hash {{%{$_[0]//{}}}}
        Or without a sub:
        my %copy = %+;
Re: %+ and cloning
by JavaFan (Canon) on Jan 11, 2010 at 11:48 UTC
    Please, please, please, if you're going to post code fragments to show differences of behaviour SHOW THE OUTPUT! - don't expect people who're going to help you copy the work you've done.

    Now, I'm just going to guess what's happening: %+ is actually a tied array, and dclone copies the tie magic.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (9)
As of 2024-04-16 09:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found