Reputation: 627
I'm struggling with the difference between arrays and scalars.
I initialize an object from Config::IniFiles
. One of the object properties is an array. During the init method, I can print the array values and the array size.
[project]
junk = Perl
junk = is
junk = complicated
From the init method, called inside constructor
my $ini = Config::IniFiles->new( -file => "config.ini", -default => 'Default' );
my $junk = $ini->val( 'project', 'junk' );
my @junk = split( /\n/, $junk );
say scalar @junk;
foreach ( @junk ) {
say $_;
}
$self->{_junk} = @junk;
3
Perl
is
complicated
Now, I implemented the getter method:
sub getJunkPatterns {
my ($self) = @_;
return $self->{_junk};
}
And call it like this
my @patterns = $self->getJunkPatterns();
say scalar @patterns;
say @patterns;
The result is not what I expected
3
3
For scalar (not array) properties this works fine. Could anyone tell me what I'm doing wrong with arrays? Does anyone know how to properly get arrays from Config::IniFiles
without the need to split them?
Upvotes: 0
Views: 434
Reputation: 66883
I take it that the code section with $ini->val(...)
is inside of a class and that _junk
that the data is written to is intended to be an array reference, the only meaningful option.
First, you can have val
from Config::IniFiles return data either as a list or as a string
If you want a multi-line/value field returned as an array, just specify an array as the receiver:
@values = $cfg->val('Section', 'Parameter');
So instead of assigning to a scalar and splitting into lines just assign to an array.
Next, the assignment $self->{_junk} = @junk;
is most likely wrong, as follows.
The array @junk
is being assigned to a scalar, the only thing a hash value can be. This means that the operation is in the scalar context, in which case what gets assigned is the number of elements of the array. So after that line _junk
has a number instead of being an arrayref, as seen in the ouput. See context in perldata.
So assign an arrayref, [@junk]
(or more efficiently \@junk
, if the surrounding code allows it).
Finally, in your getter you can simply choose to return those lines either as a list or as a reference to that list, as the answer by simbabque shows.
But you can also consider returning it like val
does, as either a string or a list, depending on the context in which the method is called. To do this check for the context using wantarray. If the method is called in the list context we return a list, while in the scalar context we return a scalar.
sub getJunkPatterns {
my ($self) = @_;
return (wantarray)
? @{$self->{_junk}};
: join "\n", @{$self->{_junk}};
}
The elements are joined by newline for the scalar return, to mimic what val
does. If you'd rather return the reference change the scalar return to : $self->{_junk};
.
Then you can use it either as
my @patterns = $object->getJunkPatterns();
or
my $pattern_string = $object->getJunkPatterns();
If you choose to return a reference to that list in the scalar context, instead of the string with lines, change the getter accordingly and then the returned scalar is an arrayref.
Upvotes: 3
Reputation: 54323
You are mixing up arrays and array references.
Your line $self->{_junk} = ['Test1', 'test2']
sets the value of the _junk
key to an array reference. You can tell that from the square brackets []
.
To get the array out of the reference, you need to dereference it. You can either do that in your getter like this:
return @{ $self->{_junk} };
Or you define your interface as an array reference and let the user deref it.
my @patterns = @{ $self->getJunkPatterns() };
Of course you need to have an array reference inside of that key in the first place. It's not possible to put an array inside anything. Data structures with more than one level have to be references in Perl.
So wherever you set it, it needs to look something like this:
sub setJunkPatterns {
my ($self, @patterns) = @_;
$self->{_junk} = \@patterns;
}
See perlref and perlreftut for more information.
You are using $self
throughout the code, but it appears that you are not inside of a class. $self
in Perl is used similar to this
in some other languages. It's the reference to the instantiated object of a class that you are working with, inside of that class. So when you instantiate an object of a certain class outside, you would never call that $self
.
Upvotes: 4