Understand Scalar Declaration - perl

I am working on some perl code that is not mine. I ran into this line and I have no idea what it is doing:
my $sum = [];
I just don't understand what this scalar is being set to.

[ LIST ]
is basically a shortcut for
do { my #anon = ( LIST ); \#anon }
It creates an array initialized with the result of the enclosed expression (if any), and returns a reference to that array.

From the documentation:
If you write just [] , you get a new, empty anonymous array. If you
write just {} , you get a new, empty anonymous hash.

Related

Initialize empty Array of Hashes of a given length - one-liner

I'd like to pre-initialize the elements of an array of hashes so that when it comes time to filling in the data, I don't need to check for the existence of various members and initialize them every loop. If I can, I'd like to pre-initialize the general form of the datastructure which should look like this:
$num_sections = 4;
# Some magic to initialize $VAR1 to this:
$VAR1 = {
'sections' => [
{},
{},
{},
{}
]
};
I would like this to work,
$ph->{sections} ||= [({} x $num_sections )];
but it results in
$VAR1 = {
'sections' => 'HASH(0x21b6110)HASH(0x21b6110)HASH(0x21b6110)HASH(0x21b6110)'
};
And no amount of playing with the () list context and {} empty hash reference seem to make it work.
This works but it's not quite a one-liner
unless ($ph->{sections})
{
push #{ $ph->{sections}}, {} foreach (1..$num_sections);
}
There's probably some perl magic that I can use to add the unless to the end, but I haven't quite figured it out.
I feel I'm so close, but I just can't quite get it.
Update Oleg points out that this probably isn't necessary at all. See comments below.
If the left-hand side of x is not in parens, x repeats the string on its LHS and returns the concatenation of those strings.
If the left-hand side of x is in parens, x repeats the value on its LHS and returns the copies.
This latter approach is closer to what you want, but it's still wrong as you'll end up with multiple references to a single hash. You want to create not only new references, but new hashes as well. For that, you can use the following:
$ph->{sections} ||= [ map { +{} } 1..$num_sections ];

Multidimensional arrays with only ONE entry

I wrote a generic function to call a stored procedure. I tried to use a multidimensional array to pass the parameters. Now it is possible, that the procedure only takes one parameter, so my multidimensional array has also only one parameter. But the lenght of such an array is 2!
$MyParameters = ("param1_name", "param1_value")
$MyParameters.Length returns 2!! Strange, why? It should return 1
$MyParameters returns correctly:
param1_name
param1_value
If I write:
$MyParameters = ("param1_name", "param1_value"), ("param2_name", "param2_value")
$MyParameters.Length returns also 2 which is correct. $MyParameters returns correctly all four elements:
param1_name
param1_value
param2_name
param2_value
Any reasons for that? Am I missing something?
What you are trying to do is creating an array of multi value object.
Here is an example to solve that issue:
$x = ,("param1","param2","param3")
x.Lenght
Will return 1 which is correct for your issue.
$x = ,("param1","param2","param3"),("param1","param2","param3")
x.Lenght
Will return 2
$x = ,("param1","param2","param3"),("param1","param2","param3")
x[0].Lenght
will return 1, thats because $x[0] is array with one element.
In addition, If you would like to create an Array of Arrays this is the way to do it:
$x = #("param1","param2","param3"),#("param1","param2","param3")
$x.Lenght
#2
$x[0].Lenght
#3

Splat for removing an item from an array

Although I know about splats, still I can't quite grasp the last line from the following code:
class Borrowable extends Decorator
constructor: (#libraryItem) ->
removeBorrower: (borrower) ->
#borrowers[t..t] = [] if ( t = #borrowers.indexOf(borrower) ) > -1
Btw, this code was copied from https://github.com/aksharp/Design-Patterns/blob/master/CoffeeScript/Decorator.coffee
Im assuming this is Destructuring Assignment, still I can't quite get my head around what's it's happening behind the scenes.
Could you help clarify this?
Let's have a closer look at the last line:
#borrowers[t..t] = [] if ( t = #borrowers.indexOf(borrower) ) > -1
I'm not sure if this form counts as Destructuring Assignment, probably it is.
First, it calls #borrowers.indexOf(borrower) to check that borrower is present inside of the #borrowers array and to get it's index.
It's conventional to use borrower in #borrowers form instead of #borrowers.indexOf(borrower) > -1, but in this case we need index of an element as well.
If borrower is present in #borrowers, it gets the part of the #borrowers array between indexes t and t
#borrowers[t..t]
which is the [borrower], and assigns it to the empty array [], thus removing the borrower from #borrowers array.
Here is js-like equivalent of this assignment:
#borrowers.splice t, 1

What does ($a,$b,$c) = #array mean in Perl?

I'd google it if I could but honestly I don't know what to search for (an inherent problem with symbol-heavy languages)!
($aSvnRemote, $aSvnLocal, $aSvnRef, $aSvnOptions) = #{$aSvnPair};
My guess is that $aSvnPair is an array of 4 values (in which case it's a very poorly named variable!) and this is just splitting it into specific variable identities...?
It's nothing more than a list assignment. The first value of the RHS is assigned to the first var on the LHS, and so on. That means
($aSvnRemote, $aSvnLocal, $aSvnRef, $aSvnOptions) = #{$aSvnPair};
is the same as
$aSvnRemote = $aSvnPair->[0];
$aSvnLocal = $aSvnPair->[1];
$aSvnRef = $aSvnPair->[2];
$aSvnOptions = $aSvnPair->[3];
The variable $aSvnPair is a reference to an array. Adding the # sigil causes the array to be referenced. In this example, the array is unpacked and it's elements are assigned to the variables on the right.
Here is an example of what is happening:
$aSvnPair= [ qw(foo bar baz xyxxy) ];
($aSvnRemote, $aSvnLocal, $aSvnRef, $aSvnOptions) = #{$aSvnPair};
After this operation, you get the following:
$aSvnRemote = "foo";
$aSvnLocal = "bar";
$aSvnRef = "baz";
$aSvnOptions = "xyxxy";
$aSvnPair should be a reference to an array so #{$aSvnPair} dereferences it. (A "reference" is the Perl equivalent of a pointer.)
The statement then assigns the values of this array to the four variables on the left-hand side, in order.
See this tutorial for some examples: Dereferencing in perl

How can I force an object attribute in Perl to be set to a full array instead of just its length?

I have an object I defined with a method, childNodes(), which returns an array. When I do something like:
my #arr = obj->childNodes() I can clearly see that it can properly return an array.
My problem is that when I try to use this method to set the attribute of another class object, Perl decides I just want the length of childNodes() rather than the full array. This is not at all what I want and ruins everything. The code I'm using for this is:
$self->{'_arr'} = obj->childNodes()
How can I make this set $self->{'_arr'} to an array instead of just a scalar number?
Thanks in advance!
When you evaluate an array in scalar context, it returns the length of the array.
You want a reference to the array:
$self->{'_arr'} = [ obj->childNodes() ];
See perldoc perlref.