How to add a scalar value (string) to an existing hash in Perl - perl

I just want to know what the process is behind merging a value into a hash.
I have a hash which has 5 to 6 keys depending on if the error outputs runtime values. The method that takes in the arguments also take an error message string in first, also. I want it to be able to add this error message string into the hash, to make one big hash basically.
This is how the method would be called:
ASC::Builder::Error->new("Simple error message here", code => "UNABLE_TO_PING_SWITCH_ERROR", switch_ip => $ip3, timeout => $t1);
The last two values assign runtime parameters/values to keys inside the context key in the error hash.
Here is a look at the error hash:
use constant ERROR_CODE => {
UNABLE_TO_PING_SWITCH_ERROR => {
category => 'Connection Error',
template => 'Could not ping switch %s in %s seconds.',
context => [qw(switch_ip timeout)],
tt => {template => 'disabled'},
fatal => 1,
wiki_page => 'www.error-solution.com/ERROR_CODE_A',
}
};
Here is my method to manipulate the error hash and construct the message
sub _create_error_hash {
my $error_string = shift; if(defined($params{code}) {
my $first_param = delete $params{code};
foreach my $key (#{$first_param->{context}}) {
$first_param->{$key} = $key;
}
my #template_args = map { $first_param->{$_}} #{$first_param->{context} };
$first_param->{message} = sprintf($first_param->{template}, #template_args); }
return bless $first_param;
}
sub _merge_hashes {
my ($message = {message => $messsage}, $first_param = {first_param => $first_param}) = # _;
#merge these two hashes and bless into $class (don't know how to merge hashes)
my %merged_hash = ($message, $first_param);
return bless $merged_hash, $class;
}
The output of _create_hash should be the input for _merge_hashes
Not sure if I have handled that properly. These methods will be use inside the new method (which is a mess right now) hence why it's not included.
That's just an attempt , of an example I seen on perlmonks, Here is the link:
http://www.perlmonks.org/?node_id=14263

I'm going to start with the simple explanation of how to merge a hash in perl, it's pretty simple.
use strict;
use warnings;
use Data::Printer;
my (%a, %b, %c);
%a = (a => 1, b => 2);
%b = (a => 0, c => 3, d => 4);
%c = (%a, %b);
p(%c); # { a => 0, b => 2, c => 3, d => 4 }
You'll note with the a keys that if there are duplicates whatever value appears in the second set will be the one that 'wins'.
I honestly have no idea what that second function is doing because it references variables that don't exist on practically every line. (The create one also does this but only on a couple lines).
From your description I think you only want a single key added so you don't really need to do that though, you should be able to just add the key to the original object: $error->{messsage} = $message
But assuming you did want to pass two hash references in and merge them, it would look something like this:
sub merge {
my ($first, $second) = #_;
my %merged = (%$first, %$second);
return bless \%merged, $class;
}

Related

How to bypass magic hooks when using hash or array elements

I'm trying to use Variable::Magic in order to catch when an element of a hash is modified:
use Variable::Magic qw(cast wizard);
my %h = (a => 1, b => 2);
cast %h, wizard store => sub {
warn "store: #_\n";
my $k = $_[2];
cast $_[0]{$k}, wizard set => sub {
warn "$k set to ${$_[0]}\n"
}
};
$h{a} = 33;
However, the second inner cast on the hash element will trigger the store magic from the hash, and go into an infinite recursion (and crash).
The only way I found around it was use the data attached via cast as a lock/flag:
use Variable::Magic qw(cast wizard);
cast %h, wizard
data => sub {0},
store => sub {
return if $_[1]++;
my $k = $_[2];
cast $_[0]{$k}, wizard set => sub {
warn "$k set to ${$_[0]}\n"
};
$_[1] = 0;
}
;
$h{a} = 33;
That looks clumsy and dumb, and I feel like I be missing something obvious.
Is there any better method? I've looked for some option to Variable::Magic::wizard to mask its own magic in the methods, but I didn't find anything.
Note: I don't care to use the heavy-weight tie instead, or some other XS module that cannot be installed with a simple apt-get; if needs be, I can write my own XS where everything would be much simpler, but I'm trying to avoid that.
store is called when the hash element is fetched as an lvalue, so $h{$k}=…, f($h{$k}) and \$h{$k} call store. So while set is called after the value is changed, store is necessarily called before it's changed.
In fact, it's called before the element is even fetched, so it's called before the element is even created when it doesn't exist. This is quite unfortunate, because it means than a simple exists check isn't sufficient.
Because the magic callback is called "at the wrong time" (when the element doesn't even exist), a solution like yours (i.e. using a flag) is the best I could devise.
That said, you should ensure that the flag is reset even if an exception occurs. This can be done using local.
Your goal appears to be to add some magic to each element of a hash, including those that will be created at a later time. To that end, I'd use the following:
use Variable::Magic qw( cast wizard );
my $hash_ele_wiz = wizard(
set => sub {
my ($ref) = #_;
say "store: $$ref";
},
);
my $hash_wiz = wizard(
data => sub {
my ($var) = #_;
cast($_, $hash_ele_wiz) for values(%$var);
return { nomg => 0 };
},
store => sub {
my ($var, $data, $key) = #_;
return if exists($var->{$key}) || $data->{nomg};
my $ele_ref = do { local $data->{nomg} = 1; \( $var->{$key} ) };
cast($$ele_ref, $hash_ele_wiz);
},
);
my %h = ( a => 1, b => 2 );
cast(%h, $hash_wiz);
$h{b} = 3; # store: 3
$h{c} = 4; # store: 4
my $ref = \$h{d};
$$ref = 5; # store: 5
It wouldn't take much to extend this to add the magic recursively. See the "Recursively cast magic on datastructures" recipe in the docs.

Perl pass hash reference to Subroutine from Foreach loop (Array of Hash)

This may be something very simple for you but i have been trying for it for more than one hour.
Ok.. Here is my code,
#collection = [
{
'name' => 'Flo',
'model' => '23423',
'type' => 'Associate',
'id' => '1-23928-2392',
'age' => '23',
},
{
'name' => 'Flo1',
'model' => '23424',
'type' => 'Associate2',
'id' => '1-23928-23922',
'age' => '25',
}];
foreach my $row (#collection) {
$build_status = $self->build_config($row);
}
sub build_config {
my $self = shift;
my %collect_rows = #_;
#my %collect_rows = shift;
print Dumper %collect_rows; exit;
exit;
}
Where $row is really an Hash. But when i Print it.. It gives output like below (I am using Dumper),
$VAR1 = 'HASH(0x20a1d68)';
You are confusing references with hashes and arrays.
An array is declared with:
my #array = (1, 2, 3);
A hash is declared with:
my %hash = (1 => 2, 3 => 4);
That's because both hashes and arrays are simply lists (fancy lists, but I digress). The only time you need to use the [] and {} is when you want to use the values contained in the list, or you want to create a reference of either list (more below).
Note that the => is just a special (ie. fat) comma, that quotes the left-hand side, so although they do the same thing, %h = (a, 1) would break, %h = ("a", 1) works fine, and %h = (a => 1) also works fine because the a gets quoted.
An array reference is declared as such:
my $aref = [1, 2, 3];
...note that you need to put the array reference into a scalar. If you don't and do it like this:
my #array = [1, 2, 3];
... the reference is pushed onto the first element of #array, which is probably not what you want.
A hash reference is declared like this:
my $href = {a => 1, b => 2};
The only time [] is used on an array (not an aref) is when you're using it to use an element: $array[1];. Likewise with hashes, unless it's a reference, you only use {} to get at a key's value: $hash{a}.
Now, to fix your problem, you can keep using the references with these changes:
use warnings;
use strict;
use Data::Dumper;
# declare an array ref with a list of hrefs
my $collection = [
{
'name' => 'Flo',
...
},
{
'name' => 'Flo1',
...
}
];
# dereference $collection with the "circumfix" operator, #{}
# ...note that $row will always be an href (see bottom of post)
foreach my $row (#{ $collection }) {
my $build_status = build_config($row);
print Dumper $build_status;
}
sub build_config {
# shift, as we're only accepting a single param...
# the $row href
my $collect_rows = shift;
return $collect_rows;
}
...or change it up to use non-refs:
my #collection = (
{
'name' => 'Flo',
...
},
{
'name' => 'Flo1',
...
}
);
foreach my $row (#collection) {
my $build_status = build_config($row);
# build_config() accepts a single href ($row)
# and in this case, returns an href as well
print Dumper $build_status;
}
sub build_config {
# we've been passed in a single href ($row)
my $row = shift;
# return an href as a scalar
return $row;
}
I wrote a tutorial on Perl references you may be interested in guide to Perl references. There's also perlreftut.
One last point... the hashes are declared with {} inside of the array because they are indeed hash references. With multi-dimentional data, only the top level of the structure in Perl can contain multiple values. Everything else underneath must be a single scalar value. Therefore, you can have an array of hashes, but technically and literally, it's an array containing scalars where their value is a pointer (reference) to another structure. The pointer/reference is a single value.

Trying to access a hash in a constant list of hashes in perl

Okay so this is my current code which works, but I need to access each error hash in a different way in order to be compatible with other parts of the program.
Here is my Error list library:
Type.pm
package ASC::Builder::Error::Type;
use strict;
use warnings;
use parent 'Exporter';
# Export the list of errors
our #EXPORT_OK = qw/
UNABLE_TO_PING_SWITCH_ERROR
/;
# List of error messages
use constant code => {
CABLING_CHECK_TOR_INCORRECT_CABLING_ERROR => {
category => 'Cabling Error',
template => "ToR cabling is not correct at T1.The uplinks must be cabled to exactly one t1 device group",
tt => { template => 'disabled'},
fatal => 1,
wiki_page =>'http://www.error-fix.com/',
},
UPDATE_IMAGE_ERROR => {
category => 'Imaging Error',
template => "Cannot determine switch model",
tt => { template => 'disabled'},
fatal => 1,
wiki_page =>'http://www.error-fix.com/',
},
UNABLE_TO_PING_SWITCH_ERROR => {
category => 'Connection Error',
template => "Could not ping switch %s in %s seconds.",
context => [ qw(switch_ip timeout) ],
tt => {template => 'disabled'},
fatal => 1,
wiki_page => 'http://www.error-fix.com/',
},
UNKNOWN_CLIENT_CERT_ID_ERROR => {
category => 'Services Error',
template => "Unknown client certificate id: %s",
context => qw(cert_id),
tt => { template => 'disabled'},
fatal => 1,
wiki_page =>'http://www.error-fix.com/',
},
# Add errors to this library
};
1;
Here is my Error.pm file.
The new method is called for accessing and outputting a new error message and the rest are either getters or are called in the new method.
package ASC::Builder::Error;
use strict;
use warnings;
use parent 'Exporter';
our #EXPORT_OK = qw/new/;
# Method for creating error message
sub new {
my ( $class, $error, %args ) = #_;
# Initialize error with data
my $self = $error;
# If the error contains context parameters... Insert parameters into string template
if( ref $self eq 'HASH' && %args) {
foreach my $key (#{ $self->{context} } ) {
# And take the ones we need
$self->{args}->{$key} = $args{$key};
}
my #template_args = map { $self->{args}->{$_} } #{ $self->{context} };
# map/insert arguments into context hash and insert into string template
$self->{message} = sprintf ($self->{template}, #template_args);
}
return bless $self, $class;
}
# Accessor for category
sub category {
return shift->{category};
}
# Accessor for message
sub template {
return shift->{template};
}
# Accessor for context
sub context {
return shift->{context};
}
# Accessor for template option
sub tt {
return shift->{tt}{template};
}
# Accessor for fatal
sub is_fatal {
return shift->{fatal};
}
# Accessor for wiki_page
sub wiki_page {
return shift->{wiki_page};
}
# Accessor for args. args are a hash ref of context parameters that are
# passed in as a list at construction
sub args {
return shift->{args};
}
# Builds the message string from the template. maps the input params from new
# into context key
#sub message {
# my ($self) = #_;
# return sprintf $self->template,
# map { $self->args->{$_} } #{ $self->context };
#}
sub message {
return shift->{message};
}
# Stringifies the error to a log message (for SB dashboard), including the
# category, message, and wiki_page.
sub stringify {
my $self = #_;
return sprintf ("%s: %s\nMore info: %s",$self->{category}, $self->{message}, $self->{wiki_page});
}
1;
I will also include my test (where I am running this program & testing the error output). This also shows how an error is called. In the systems code it would be called like so:
ASC::Builder:Error->new(UNABLE_TO_PING_SWITCH_ERROR, switch_ip => 192.192.0.0, timeout => 30);
Error.t
#!/usr/bin/env perl
use lib ('./t/lib');
use strict;
no strict 'refs';
use warnings;
use ASC::Builder::Error;
use ASC::Builder::Error::Type;
use Test::More;
use Test::Exception;
use LWP::Simple 'head'; # Used to test if wiki link is giving a response
subtest 'Functionality of Error' => sub {
my $example_error = {
category => 'Connection Error',
template => 'Could not ping switch %s in %s seconds.',
context => [ qw(switch_ip timeout) ],
tt => {template => 'disabled'},
fatal => 1,
wiki_page => 'http://www.error-fix.com/',
};
# Correct case
{
my $error = ASC::Builder::Error->new( code => $example_error, timeout => 30, switch_ip => '192.192.0.0' );
isa_ok ($error, 'ASC::Builder::Error');
can_ok ($error, 'category');
is ($error->category(), 'Connection Error', 'Return the correct category');
can_ok ($error, 'template');
is ($error->template(), 'Could not ping switch %s in %s seconds.', 'Return the correct category');
can_ok ($error, 'tt');
is ($error->tt(), 'disabled', 'Return the correct tt template');
can_ok ($error, 'context');
is_deeply($error->context(), ['switch_ip', 'timeout'], 'Return the correct context params');
can_ok ($error, 'is_fatal');
ok($error->is_fatal(), 'Return the correct value');
can_ok ($error, 'message');
is ($error->message(), 'Could not ping switch 192.192.0.0 in 30 seconds.', 'Return the correct message');
can_ok ($error, 'stringify');
is ($error->stringify(), "Connection Error : Could not ping switch 192.192.0.0 in 30 seconds.\nMore info: http://www.error-fix.com/" , 'stringify creates the correct message');
};
# Too many arguments (this is okay)
lives_ok( sub { ASC::Builder::Error->new($example_error, timeout => 1, switch_ip => 2, extra => 3 ) }, 'Creating with too many arguments lives. (allows for additional context string to be added in the code)' );
};
subtest 'Correctness of Type.pm' => sub {
# These test cases contain all the errors from Type.pm
my #test_cases = (
{
name => 'UNABLE_TO_PING_SWITCH_ERROR',
args => {
switch_ip => '192.192.0.0',
timeout => 30,
},
message => 'Could not ping switch 192.192.0.0 in 30 seconds.',
},
);
foreach my $t (#test_cases) {
subtest $t->{name} => sub {
no strict 'refs'; # Because we need to use variable to get to a constant
ASC::Builder::Error::Type->import($t->{name});
# Create the Error object from the test data
# Will also fail if the name was not exported by Type.pm
my $error;
lives_ok( sub { $error = ASC::Builder::Error->new( &{ $t->{name} },%{ $t->{args} }) }, 'Error can be created');
# See if it has the right values
is ($error->message, $t->{message}, 'Error message is correct');
# Using LWP::Simple to check if the wiki page link is not broken
#ok head($error->wiki_page); #CANT'T GET THIS TEST TO WORK
}
}
};
done_testing;
I am trying to change it so that I can call each error something like:
ASC::Builder:Error->new(code => UNABLE_TO_PING_SWITCH_ERROR, switch_ip => 192.192.0.0, timeout => 30);
Your constructor expects that you pass it the following arguments: scalar, hash. The scalar is then used in the code as a hashref
my ($class, $error, %args) = #_;
my $self = $error;
# If the error contains [...]
if (ref $self eq 'HASH' && %args)
When you call it with
ASC::Builder:Error->new(UNABLE_TO_PING_SWITCH_ERROR, ...
that is exactly what is happening and all is well. If you want to call it as
ASC::Builder:Error->new(code => UNABLE_TO_PING_SWITCH_ERROR, ...
then you'd be passing a whole hash to it, with an even number of elements. There is no hashref (scalar) first. The constructor as it stands should give you an error about a list with odd number of elements assigned to hash, as it will first take the scalar string 'code' into $error and then attempt to assign the remaining list, UNABLE.., ... to a hash. Alas, that rest now has an odd number of elements what doesn't work for a hash. Remember that (a => 'A', b => 'B') is the same as ('a', 'A', 'b', 'B'), and when a is removed the rest can't be a hash any more.
If you want to call it that way and have the processing in your constructor the same, you'd need to change the constructor to first fetch the value of the key 'code' from the submitted hash (into $error) and remove that element from it, so that the rest can then be assigned to %args, for later processing. Some example code would be
my ($class, %args) = #_;
my $self = delete $args{code};
# Now %args contains what is needed by existing code
The delete removes the element from hash, and returns it.
delete EXPR
Given an expression that specifies an element or slice of a hash, delete deletes the specified elements from that hash so that exists() on that element no longer returns true. Setting a hash element to the undefined value does not remove its key, but deleting it does; see exists.
[...]
In list context, returns the value or values deleted, or the last such element in scalar context.
You can also support both calling conventions, by pre-processing #_ once $class has been shift-ed from it. If it does not contain a hashref first, you do the above (or something like it), otherwise you need not. Your current processing stays as it is. For example
my $class = shift;
my ($self, %args);
if (ref $_[0] eq 'HASH') {
$self = shift #_;
%args = #_;
}
else {
%args = #_;
$self = delete $args{code};
}
You can add more checking at this point. The above can be done differently, I tried to keep it clear.
In new, this is what you have (from your test):
$error = code; # Scalar or Hash Reference (depending on scope of code constant)
%args = (UNABLE_TO_PING_SWITCH_ERROR, switch_ip => 192.192.0.0, timeout => 30);
Which is not what I think you want to have:
$args{UNABLE_TO_PING_SWITCH_ERROR} = 'switch_ip';
$args{'192.192.0.0'} = 'timeout';
$args{30} = undef;
This should be true even with code and UNABLE_TO_PING_SWITCH_ERROR being either scalars and/or a hash references.
You need to alter new to determine if the first one/two arguments are hash references and/or there is an even number of arguments after it.

Perl method to create an error object using bless. Not sure about the inner-workings of this method

I received a solution for creating an object which is a hash with 5 keys. But I am not sure how it exactly works.
This is my example of the error library, I only included one error for the purpose of this question.
ErrorLibrary.pm
package ASC::Builder::ErrorLibrary;
use constant {
CABLING_ERROR => {
code => 561,
message => "cabling is not correct at T1.",
tt => { template => 'disabled'},
fatal => 1,
wiki_page =>'http://www.e-solution.com/index.php/ARC/Builder/ErrorCodes/CABLING_ERROR',
}
};
This is my error file which contains a number of methods; the new() that is use for posting an error.
The new method can accept the Error hash which are found in the ErrorLibrary or else it can accept a string which is the old way in which the error message were implemented in the system.
Example:
die ASC::Builder::Error->new(CABLING_ERROR);
Error.pm
package ASC::Builder::Error;
sub new {
my ($package, $first_param) = (shift, shift);
if (ref $first_param eq 'HASH') {
my %params = #_;
return bless { message => $first_param->{message}, code => $first_param->{code}, tt => $first_param->{tt}, fatal => $first_param->{fatal}, wiki_page => $first_param->{wiki_page}, %params}, $package;
}
else {
my %params = #_;
return bless {message => $first_param, %params}, $package;
}
}
What I want to understand about this new() method is what exactly is happening when I assign each key of the error hash to $first_param an then bless all them. Is it gathering all the attributes together and creating an object out of the attributes by using the bless function?
The Error.pm also contains the following methods which allow the value of each key to be accessed.
package ASC::Builder::Error;
sub message {
return $_[0]->{message};
}
sub tt {
return $_[0]->{tt};
}
sub code {
return $_[0]->{code};
}
sub fatal {
return $_[0]->{fatal};
}
sub wiki_page {
return $_[0]->{wiki_page};
}
But as I said I mainly just want to understand what is exactly happening in the new() method.
In Perl, objects are just regular data structures that have been blessed. This is explained in perlobj:
Objects are merely Perl data structures (hashes, arrays, scalars, filehandles, etc.) that have been explicitly associated with a particular class.
That explicit association is created by the built-in bless function, which is typically used within the constructor subroutine of the class.
When you call
bless { foo => 'bar' }, $class;
in a constructor, you
create a reference to an anonymous hash
convert the hash reference to an object by passing it to bless
The above can be rewritten as follows, which makes it clearer that objects are just regular Perl data structures under the hood:
my $self = { foo => 'bar' }; # create a hash reference
bless $self, $class; # convert the hash reference to an object
You can add as few or as many keys to this hash as you want. It's convenient to use hash keys as attributes or properties that describe an object:
my $self = {
height => 'tall',
color => 'purple',
weight => 17
};
bless $self, $class; # object has three attributes
In your code:
return bless {
message => $first_param->{message},
code => $first_param->{code},
tt => $first_param->{tt},
fatal => $first_param->{fatal},
wiki_page => $first_param->{wiki_page},
%params
}, $package;
you create a reference to an anonymous hash with at least five keys (more if %params is not empty); you then convert the hashref to an object. You can think of message, code, tt, fatal, and wiki_page as being attributes of the object.

What are anonymous hashes in perl?

$hash = { 'Man' => 'Bill',
'Woman' => 'Mary,
'Dog' => 'Ben'
};
What exactly do Perl's “anonymous hashes” do?
It is a reference to a hash that can be stored in a scalar variable. It is exactly like a regular hash, except that the curly brackets {...} creates a reference to a hash.
Note the usage of different parentheses in these examples:
%hash = ( foo => "bar" ); # regular hash
$hash = { foo => "bar" }; # reference to anonymous (unnamed) hash
$href = \%hash; # reference to named hash %hash
This is useful to be able to do, if you for example want to pass a hash as an argument to a subroutine:
foo(\%hash, $arg1, $arg2);
sub foo {
my ($hash, #args) = #_;
...
}
And it is a way to create a multilevel hash:
my %hash = ( foo => { bar => "baz" } ); # $hash{foo}{bar} is now "baz"
You use an anonymous hash when you need reference to a hash and a named hash is inconvenient or unnecessary. For instance, if you wanted to pass a hash to a subroutine, you could write
my %hash = (a => 1, b => 2);
mysub(\%hash);
but if there is no need to access the hash through its name %hash you could equivalently write
mysub( {a => 1, b => 2} );
This comes in handy wherever you need a reference to a hash, and particularly when you are building nested data structures. Instead of
my %person1 = ( age => 34, position => 'captain' );
my %person2 = ( age => 28, position => 'boatswain' );
my %person3 = ( age => 18, position => 'cabin boy' );
my %crew = (
bill => \%person1,
ben => \%person2,
weed => \%person3,
);
you can write just
my %crew = (
bill => { age => 34, position => 'captain' },
ben => { age => 28, position => 'boatswain' },
weed => { age => 18, position => 'cabin boy' },
);
and to add a member,
$crew{jess} = { age => 4, position => "ship's cat" };
is a lot neater than
my %newperson = ( age => 4, position => "ship's cat" );
$crew{jess} = \%newperson;
and of course, even if a hash is created with a name, if its reference is passed elsewhere then there may be no way of using that original name, so it must be treated as anonymous. For instance in
my $crew_member = $crew{bill}
$crew_member is now effectively a reference to an anonymous hash, regardless of how the data was originally constructed. Even if the data is (in some scope) still accessible as %person1 there is no general way of knowing that, and the data can be accessed only by its reference.
It's quite simple. They allow you to write
push #hashes, { ... };
f(config => { ... });
instead of
my %hash = ( ... );
push #hashes, \%hash;
my %config = ( ... );
f(config => \%config);
(If you want to know the purpose of references, that's another story entirely.)
Anything "anonymous" is a data structure that used in a way where it does not get a name.
Your question has confused everyone else on this page, because your example shows you giving a name to the hash you created, thus it is no longer anonymous.
For example - if you have a subroutine and you want to return a hash, you could write this code:-
return {'hello'=>123};
since it has no name there - it is anonymous. Read on to unwind the extra confusion other people have added on this page by introducing references, which are not the same thing.
This is another anonymous hash (an empty one):
{}
This is an anonymous hash with something in it:
{'foo'=>123}
This is an anonymous (empty) array:
[]
This is an anonymous array with something in it:
['foo',123]
Most of the time when people use these things, they are really trying to magically put them inside of other data structures, without the bother of giving them a waste-of-time temporary name when they do this.
For example - you might want to have a hash in the middle of an array!
#array=(1,2,{foo=>3});
that array has 3 elements - the last element is a hash! ($array[2]->{foo} is 3)
perl -e '#array=(1,2,{foo=>1});use Data::Dumper;print Data::Dumper->Dump([\#array],["\#array"]);'
$#array = [
1,
2,
{
'foo' => 1
}
];
Sometimes you want to don't want to pass around an entire data structure, instead, you just want to use a pointer or reference to the data structure. In perl, you can do this by adding a "\" in front of a variable;
%hashcopy=%myhash; # this duplicates the hash
$myhash{test}=2; # does not affect %hashcopy
$hashpointer=\%myhash; # this gives us a different way to access the same hash
$hashpointer->{test}=2;# changes %myhash
$$hashpointer{test}=2; # identical to above (notice double $$)
If you're crazy, you can even have references to anonymous hashes:
perl -e 'print [],\[],{},\{}'
ARRAY(0x10eed48)REF(0x110b7a8)HASH(0x10eee38)REF(0x110b808)
and sometimes perl is clever enough to know you really meant reference, even when you didn't specifically say so, like my first "return" example:
perl -e 'sub tst{ return {foo=>bar}; }; $var=&tst();use Data::Dumper;print Data::Dumper->Dump([\$var],["\$var"]);'
$var = \{
'foo' => 'bar'
};
or:-
perl -e 'sub tst{ return {foo=>bar}; }; $var=&tst(); print "$$var{foo}\n$var->{foo}\n"'
bar
bar