Beefy Boxes and Bandwidth Generously Provided by pair Networks RobOMonk
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

dereferencing a stringfied referent

by clueless newbie (Friar)
on Jun 12, 2010 at 09:20 UTC ( #844336=perlquestion: print w/ replies, xml ) Need Help??
clueless newbie has asked for the wisdom of the Perl Monks concerning the following question:

Greetings,

Given a stringified referent, how does one dereference it? IE: What does sub f need to be so that the results from (2) match the results from (1)?

Many thanks!
#! use Data::Dumper; use strict; use warnings; sub f { # (0) # }; my $str; my $ref=[1,2]; print Data::Dumper->Dump([\$ref],[qw(*ref)]); # (1) $str=''.$ref; print Data::Dumper->Dump([\$str],[qw(*str)]); # what do I need to do to $str so that (2) dump the original data stru +cture my $newref=f($str); print Data::Dumper->Dump([\$newref],[qw(*newref)]);# (2)
edited to remove {} block

Comment on dereferencing a stringfied referent
Download Code
Re: dereferencing a stringfied referent
by almut (Canon) on Jun 12, 2010 at 09:47 UTC

    You can't, at least not easily. Sure, you could write some XS code that puts the address back into the RV field of a reference, but you're not meant to mess with addresses like in C.  It's asking for trouble, because Perl manages memory via reference counts1. And what if the item your stringified "reference" points to no longer exists when you dereference it?

    What is the real problem you're trying to solve, for which you would need this functionality?

    ___

    1 those reference counts are automatically incremented/decremented as needed as long as you use normal Perl references, but they're not updated for stringified references.

      Hi,

      I'm working with a SIG{__WARN__} and I'm calling Carp::Longmess. By default, I'm getting those lovely stringified referents which I want. But I also need to get the data structures those stringified referents dereference to.

      I suppose I could get Carp::Longmess to expand out the un blessed data structures then capture them via "regex", but I was hoping that there was a cleaner way.

      This kind of gets me what I'm after without actually dereferencing the stringified referent. The replacement format_arg is "stashing" the stringified data structure while returning its stringified referent
      #! use Carp::Heavy; use Data::Dumper; use Scalar::Util; use strict; use warnings; my @stash; BEGIN { # Now redefine Carp::format_arg so we can dump refs too! no warnings qw(once redefine); *Carp::format_arg = sub { # shameless stolen from b. d foy package Carp; my $arg_s=shift; my $return_s; if (not defined $arg_s) { $return_s='undef'; } elsif (Scalar::Util::blessed($arg_s)) { # an object $return_s="'".ref($arg_s)."(object/class)'"; } elsif (ref($arg_s)) { # a ref require Data::Dumper; local $Data::Dumper::Indent=0; local $Data::Dumper::Terse=0; # deparse CodeRefs local $Data::Dumper::Deparse=ref($arg_s) eq 'CODE'; $return_s=Data::Dumper::Dumper($arg_s); $return_s=~ s/^\$VAR\d+\s*=\s*//; $return_s=~ s/;\s*$//; $return_s=~ s/ */ /g if (ref($arg_s) eq 'CODE'); push(@stash,$return_s); $return_s="'$arg_s($#stash)'"; } else { $return_s=$arg_s; $return_s=~ s/'/\\'/g; $return_s=str_len_trim($arg_s,$Carp::Heavy::MaxArgLen); $return_s="'$arg_s'" unless $arg_s =~ /^-?[\d.]+\z/; } $return_s=~ s/([[:cntrl:]]|[[:^ascii:]])/sprintf("\\x{%x}",ord +($1))/eg; return $return_s; }; }; # BEGIN: $SIG{__WARN__}=sub { my $buffer=Carp::longmess(); print STDOUT "$buffer\n"; print STDOUT "$_: $stash[$_]\n" for (0..$#stash); @stash=(); }; # Just some code to test use CGI; my $q=CGI->new(); main(1,[2],{3=>$q},sub { return "huh" },$q); sub main { warn "main"; shift; shift; subroutine(@_); }; sub subroutine { warn "sub"; die "just for fun!"; };
      It yields:
      at Dump.pl line 62 main::main(1, 'ARRAY(0x1bba4ec)(0)', 'HASH(0x1b58b5c)(1)', 'CO +DE(0x1a6d4a4)(2)', 'CGI(object/class)') called at Dump.pl line 59 0: [2] 1: {'3' => bless( {'.parameters' => [],'use_tempfile' => 1,'.charset' +=> 'ISO-8859-1','.fieldnames' => {},'param' => {},'escape' => 1}, 'CG +I' )} 2: sub { use warnings; use strict 'refs'; return 'huh';} at Dump.pl line 68 main::subroutine('HASH(0x1b58b5c)(0)', 'CODE(0x1a6d4a4)(1)', ' +CGI(object/class)') called at Dump.pl line 64 main::main(1, 'ARRAY(0x1bba4ec)(2)', 'HASH(0x1b58b5c)(3)', 'CO +DE(0x1a6d4a4)(4)', 'CGI(object/class)') called at Dump.pl line 59 0: {'3' => bless( {'.parameters' => [],'use_tempfile' => 1,'.charset' +=> 'ISO-8859-1','.fieldnames' => {},'param' => {},'escape' => 1}, 'CG +I' )} 1: sub { use warnings; use strict 'refs'; return 'huh';} 2: [2] 3: {'3' => bless( {'.parameters' => [],'use_tempfile' => 1,'.charset' +=> 'ISO-8859-1','.fieldnames' => {},'param' => {},'escape' => 1}, 'CG +I' )} 4: sub { use warnings; use strict 'refs'; return 'huh';} just for fun! at Dump.pl line 69.
Re: dereferencing a stringfied referent
by LanX (Abbot) on Jun 12, 2010 at 12:13 UTC
    Hi

    As almut already told you there is no clean straight forward solution.

    These kind of problems normally originate from trying to use a reference as hash key...there are moduls with specially tied hashes to handle this.

    Their basic solution is to memorize the relation in a look-up-table, whenever a stringification is needed.

    $ref_of{$stringification}=$reference;

    Keep in mind that the refcounter is automatically incremented as long as the table entry exists, this could lead to new problems if you don't take care about memory consumption...

    Cheers Rolf

      Thank you!
Re: dereferencing a stringfied referent
by sflitman (Hermit) on Jun 12, 2010 at 17:52 UTC
    I've also been curious about this. I've had to convert references to YAML or JSON and output to a log file, but I agree where this becomes a big issue is where the stringified referent is being used as a hash key. Could anyone inform me if it is reasonable to use a JSON encoded version of the referenced object as a hash key instead of a stringified referent?

    SSF

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (7)
As of 2014-04-17 03:46 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (439 votes), past polls