I keep running into problems with dereferencing, especially when returning values from functions.
The issue seems to be that whenever you return anything other than a scalar you are actually returning that object by reference – which is fine by me – but say when we pass these references to other functions and we need access to their guts again how do we do that correctly?
I keep running into errors like: “expecting even number of params got reference” or something to the effect.
Is there a general rule of thumb that I can use to simplify this whole process? I almost wish I didnt have to worry about dereferencing!
Here’s an example of something I tried to do earlier today, and ran into all kinds of dereferencing problems that I spent a couple of hours trying to bash my way through — so after reading, trying and failing, I’m here to ask you for the lowdown.
Person object
Person
has name [Str]
has madeby [Str]
has height [Num]
has id [Num]
Various ways of making a Person object
sub person_maker{
my($this,%options) = @_;
my $person = Person->new(%options);
return $person;
}
sub make_person_named_james{
my($this,$options) = @_;
my $default = { name => 'James', madeby => 'name' };
$options = ($options,$defaults); #merge default and options hash
return($this->person_maker($options));
}
sub make_person_from_id{
my($this,$id) = @_;
my $default = { name => 'nameless person', madeby => 'id' };
$default = ($default,{ id => $id });
return($this->person_maker($default);
}
sub make_person_from_person{
my($this,$person) = @_;
my $person_options = {
name => $person->name().'_twin',
height => $person->height(),
id => $person->id() + 1,
madeby => 'person'
};
return($this->person_make($person_options));
}
- Func returns hash object => it actually returns as a hash
reference - Func returns hash reference => it actually returns as a
scalar - Func returns array object => it actually returns an array
reference - Func returns array reference => it actually returns a scalar
? - Func returns a scalar => it actually returns the value of the
scalar?
Correct me if I’ve understood any of that wrong.
Then another issue for me is at the point of consuming the arguments of a function..
Depending on what I return back these bad boys are all going to behave differently!
sub myfunc{
my($self,$args) = @_ # list of arguments (what if the args are mixed?)
OR
my($self,$args) = $_ # scalar (this wont work here $args will by undef
OR
my $self = shift; # pop the first arg
my $args = shift; # pop the second arg
OR
my $self = $_[0]
my $args = $_[1]
Plus! There are way too many documents out there, many of them outdated, so it’s hard to figure out exactly what the right or best thing to do is in these situations.
If someone has a magic chart that spells out when to use these different setups, and how to dereference given certain scenarios, blessed Hashes, Hash Ref, Scalar, etc etc. I would be eternally grateful as I’ve wasted hours trying to decipher this.
All references are scalar values
De-referencing a reference requires that you know the type of the reference. The type of a reference can be found by using the
reffunction.De-referencing different types
Scalar reference:
$$scalar_refArray reference:
@$array_refHash reference:
%$hash_ref@_@_contains aliases of the parametres. Modifying@_results in the modification of the original values. Always make a copy of the parametres as soon as possible and work on those copies; which you can safely modify without the original values changing.Arguments and return values
In Perl, all function call arguments are flattened (collapsed) to a list (thus losing their identities) and so are the return values. From a function’s perspective, it is able to accept only and a single list of values and can return only a single list of values.
Example scenarios:
Scalar argument to a function:
The same applies to all references; references are scalar values.
Array argument to a function:
Hash argument to a function:
Always pass references when multiple lists (arrays) or hashes are involved. This way, you can identify the lists individually.
$_and@_are differentQuoting your code (which uses
$_incorrectly):$_is called the default variable and is used in a number of situations where no explicit variable is stated.@_on the other hand is only used for holding array parametres (aliases) inside a function. To refer to each element, we can use:$_[0],$_[1], et cetera.References
You can read more about predefined variables in Perl from
perldoc perlvar. I always useperldoc -v '$special_variable'from my terminal. If you use Windows, the single quotes have to be replaced with double quotes:perldoc -v "$special_variable".Perl subroutines:
perldoc perlsubPerl references and nested data structures:
perldoc perlref