Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I convert the stringified version of array reference to actual array reference in Perl?

Tags:

perl

Is there any way to get Perl to convert the stringified version e.g (ARRAY(0x8152c28)) of an array reference to the actual array reference?

For example

perl -e 'use Data::Dumper; $a = [1,2,3];$b = $a; $a = $a.""; warn Dumper (Then some magic happens);'

would yield

$VAR1 = [
      1,
      2,
      3
    ];
like image 846
Tim Avatar asked Nov 04 '09 01:11

Tim


People also ask

How to access a referenced array in Perl?

The Magic of Array References in Perl is to use array references to access nested data. The syntax for accessing a referenced array seems a little trick at first, and I’ll put the code here, and then explain how it works. The reference is actually created using the backslash symbol. Perl flattens all nested data, and mashes all the data together.

How do I assign an array to a variable in Perl?

To assign an array reference into a variable, use the backslash (\) operator as shown below If you try to print the $array_ref variable, you’ll get something like the following. The Perl array reference can also be passed to a subroutine as shown below.

How to get the first element of an array in Perl?

This statement gives the first element of @numbers array. This is same as $numbers [0] Instead of storing the reference into the variable, the array elements can be accessed directly from Perl built-in variable. # Get all the elements of @numbers array. @ { $_ [0] } # Get a particular element.

How to pass an array reference to a subroutine in Perl?

The Perl array reference can also be passed to a subroutine as shown below. In the above code snippet, we need to de-reference the array, so that the subroutine can take the elements from the original array. Following are some of the advantages of passing the reference to a subroutine, instead of passing the whole array.


3 Answers

Yes, you can do this (even without Inline C). An example:

use strict;
use warnings;

# make a stringified reference
my $array_ref = [ qw/foo bar baz/ ];
my $stringified_ref = "$array_ref";

use B; # core module providing introspection facilities
# extract the hex address
my ($addr) = $stringified_ref =~ /.*(0x\w+)/;
# fake up a B object of the correct class for this type of reference
# and convert it back to a real reference
my $real_ref = bless(\(0+hex $addr), "B::AV")->object_2svref;

print join(",", @$real_ref), "\n";

but don't do that. If your actual object is freed or reused, you may very well end up getting segfaults.

Whatever you are actually trying to achieve, there is certainly a better way. A comment to another answer reveals that the stringification is due to using a reference as a hash key. As responded to there, the better way to do that is the well-battle-tested Tie::RefHash.

like image 161
ysth Avatar answered Oct 26 '22 13:10

ysth


The first question is: do you really want to do this?

Where is that string coming from?

If it's coming from outside your Perl program, the pointer value (the hex digits) are going to be meaningless, and there's no way to do it.

If it's coming from inside your program, then there's no need to stringify it in the first place.

like image 35
ScottJ Avatar answered Oct 26 '22 13:10

ScottJ


Yes, it's possible: use Devel::FindRef.

use strict;
use warnings;
use Data::Dumper;
use Devel::FindRef;

sub ref_again {
   my $str = @_ ? shift : $_;
   my ($addr) = map hex, ($str =~ /\((.+?)\)/);
   Devel::FindRef::ptr2ref $addr;
}

my $ref = [1, 2, 3];
my $str = "$ref";
my $ref_again = ref_again($str);

print Dumper($ref_again);
like image 39
tobyink Avatar answered Oct 26 '22 14:10

tobyink