Perl: Return anonymous array from a subroutine - perl

I'm trying to return an anonymous array from a subroutine, however, when dumping the returned variable I only see one value (I'm expecting two).
Here is my code:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my $fruits_ref = generate_fruits();
print "Fruits: " . Dumper($fruits_ref) . "\n";
sub generate_fruits
{
return ("Apple", "Orange");
}
This outputs:
Fruits: $VAR1 = 'Orange';
How do I get the subroutine to return that array ref?

Anonymous arrays are constructed with square brackets.
return [ 'Apple', 'Orange' ]

You're not returning an array (or a reference to array), you're returning a list. A reference to anonymous array is ["Apple", "Orange"]
List becomes its last element when you pass it to scalar context. To pass to list context, you could do
my #fruits = generate_fruits();
But that is likely not what you need - you seem to need a reference. For that, just use square brackets.
Oh, another alternative is
my $fruits_ref = [generate_fruits()];

Related

How to print the values of array reference in PERL?

I have a defined days array with the square bracket in Perl. I want to access each element of the array.
A similar example from the code below(This is just a snippet of code):-
#days = [a,2,3];
foreach(#days){print "$_\n";}
print "\n\n #days";
And output is
ARRAY(0x2032950)
ARRAY(0x2032950)
I need to access the array elementS but I cannot change the #days declaration.
The following code is not working as well:-
#days = [a,2,3];
use feature qw<say>;
foreach(#days){print "$_\n";}
print "\n\n #days\n";
print "#$days\n";
say $_ for $days->#*;
Attn: OP - array declaration is not correct.
If you can not change array declaration (it is not clear what is the cause) then print them with following code
use strict;
use warnings;
use feature 'say';
my #days = ['a',2,3];
say for #{$days[0]};
say "Number of elements: " . scalar #{$days[0]};
Proper code should be
use strict;
use warnings;
use feature 'say';
my #days = ('a',2,3);
say for #days;
say "Number of elements: " . scalar #days;
Following piece of code demonstrates how array created, using this information is easy to figure out how to access stored values of array elements
use strict;
use warnings;
use feature 'say';
use Data::Dumper;
my #days = ['a',2,3];
say Dumper(\#days);
Output
$VAR1 = [
[
'a',
2,
3
]
];
I think you accidentally have an extra layer in your data.
When you use the square braces, you are actually using the anonymous array constructor. That returns an array reference, which is a scalar (single item). You probably didn't mean to assign that to an array since you get an array of one element where that one element is the reference. This effectively makes a double-level hash:
my #days = [ 'a', 1, 2 ]; # probably wrong
Since the array reference is a scalar, you likely mean to assign it to a scalar with the $ (single item) sigil. you don't use # because the reference points to an array. The sigil is more about the container than the data:
my $days = [ 'a', 1, 2 ];
When you have the array reference, there are various ways to get its elements. Since it's a simple scalar (not a single element access to an array or hash), you can prefix it with # (the multiple element sigil) to treat it as an array:
my #elements = #$days;
# OR
foreach my $element ( #$days ) {
say "Element: $element";
}
You can even interpolate that just like a named array:
say "Elements are #$days";
Here's a way to print the array reference:
#! /usr/bin/env perl
use warnings;
use strict;
use feature qw<say>;
my $arr_ref = [1,2,3];
say for $arr_ref->#*;

Why does perl only dereference the last index when the range operator is used?

I have an array, #array, of array references. If I use the range operator to print elements 1 through 3 of #array, print #array[1..3], perl prints the array references for elements 1 through 3.
Why when I try to dereference the array references indexed between 1 and 3, #{#array[1..3]}, perl only dereferences and prints out the last element indexed in the range operator?
Is there a way to use the range operator while dereferencing an array?
Example Code
#!/bin/perl
use strict;
use warnings;
my #array = ();
foreach my $i (0..10) {
push #array, [rand(1000), int(rand(3))];
}
foreach my $i (#array) {
print "#$i\n";
}
print "\n\n================\n\n";
print #{#array[1..3]};
print "\n\n================\n\n";
From perldata:
Slices in scalar context return the last item of the slice.
#{ ... } dereferences a scalar value as an array, this implies that the value being dereferenced is in scalar context. From the perldata quote above we know that this will return the last element. Therefore the result is the last element.
A more reasonable approach would be to loop through your slice and print each individual array reference:
use strict;
use warnings;
use feature qw(say);
my #array_of_arrayrefs = (
[qw(1 2 3)],
[qw(4 5 6)],
[qw(7 8 9)],
[qw(a b c)],
);
foreach my $aref ( #array_of_arrayrefs[1..3] ) {
say join ',', #$aref;
}
#{#array[1..3]} is a strange-looking construct. #{ ... } is the array dereference operator. It needs a reference, which is a type of scalar. But #array[ ... ] produces a list.
This is one of those situations where you need to remember the rule for list evaluation in scalar context. The rule is that there is no general rule. Each list-producing operator does its own thing. In this case, apparently the array slice operator used in scalar context returns the last element of the list. #array[1..3] in scalar context is the same as $array[3].
As you have noticed, this is not useful. Array slices aren't meant to be used in scalar context
If you want to flatten a 2-dimensional nested array structure into a 1-dimensional list, use map:
print join ' ', map { #$_ } #array[1..3]
You still use the range operator for slicing. You just need some kind of looping construct (e.g. map) to apply the array dereference operator separately to each element of the outer array.
The #{ ... } construction dereferences the scalar value of the code within the braces as an array
I'm unclear what you expect from #{ #array[1..3] }, but the list#array[1..3] in scalar context returns just the last element of the list -- $array[3] -- so you are asking for #{ $array[3] } which I guess is what you got
If you explain what you want to print then I am sure we can help, but dereferencing a list makes little sense
#array[1..3] is a list of 3 array references. You can't dereference them all at once, so you should iterate over this list and dereference each element separately:
print #$_ for #array[1..3];
print "#$_\n" for #array[1..3]; # for better looking output

Perl: Calling a module method inside [ ]

Using an example, let a perl program start in the following fashion:
use strict;
use warnings;
use Time::HiRes;
What's the difference between
my $request_start_epoch = [Time::HiRes::gettimeofday];
and
my $request_start_epoch = Time::HiRes::gettimeofday;
?
The former calls the function in list context, assembles an anonymous array containing the elements of the returned list, and sets $request_start_epoch to a reference to that array.
The latter calls the function in scalar context and stores its return-value in $request_start_epoch.
These will almost always be different; the only time they would be the same is if the function's behavior in scalar context is to wrap up its list-context results in an anonymous array and return a reference to it. I've never seen any method written like that, but I'm sure someone somewhere has done it at some point!
The brackets [] convert what is returned by gettimeofday to an array reference. In your case, it would be a one element array.
Creating an array reference.
$arr_ref = [ 1,2,3,4,5 ];
Deferencing it.
#{ $arr_ref };
Accessing an element.
$ { $array_ref }[0]

Subroutine that returns hash - breaks it into separate variables

I have a subroutine that returns a hash. Last lines of the subroutine:
print Dumper(\%fileDetails);
return %fileDetails;
in this case the dumper prints:
$VAR1 = {
'somthing' => 0,
'somthingelse' => 7.68016712043654,
'else' => 'burst'
}
But when I try to dump it calling the subroutine with this line:
print Dumper(\fileDetailsSub($files[$i]));
the dumper prints:
$VAR1 = \'somthing';
$VAR2 = \0;
$VAR3 = \'somthingelse';
$VAR4 = \7.68016712043654;
$VAR5 = \'else';
$VAR6 = \'burst';
Once the hash is broken, I can't use it anymore.
Why does it happen? And how can I preserve the proper structure on subroutine return?
Thanks,
Mark.
There's no such thing as returning a hash in Perl.
Subroutines take lists as their arguments and they can return lists as their result. Note that a list is a very different creature from an array.
When you write
return %fileDetails;
This is equivalent to:
return ( 'something', 0, 'somethingelse', 7.68016712043654, 'else', 'burst' );
When you invoke the subroutine and get that list back, one thing you can do is assign it to a new hash:
my %result = fileDetailsSub();
That works because a hash can be initialized with a list of key-value pairs. (Remember that (foo => 42, bar => 43 ) is the same thing as ('foo', 42, 'bar', 43).
Now, when you use the backslash reference operator on a hash, as in \%fileDetails, you get a hash reference which is a scalar the points to a hash.
Similarly, if you write \#array, you get an array reference.
But when you use the reference operator on a list, you don't get a reference to a list (since lists are not variables (they are ephemeral), they can't be referenced.) Instead, the reference operator distributes over list items, so
\( 'foo', 'bar', 'baz' );
makes a new list:
( \'foo', \'bar', \'baz' );
(In this case we get a list full of scalar references.) And this is what you're seeing when you try to Dumper the results of your subroutine: a reference operator distributed over the list of items returned from your sub.
So, one solution is to assign the result list to an actual hash variable before using Dumper. Another is to return a hash reference (what you're Dumpering anyway) from the sub:
return \%fileDetails;
...
my $details_ref = fileDetailsSub();
print Dumper( $details_ref );
# access it like this:
my $elem = $details_ref->{something};
my %copy = %{ $details_ref };
For more fun, see:
perldoc perlreftut - the Perl reference tutorial, and
perldoc perlref - the Perl reference reference.
Why not return a reference to the hash instead?
return \%fileDetails;
As long as it is a lexical variable, it will not complicate things with other uses of the subroutine. I.e.:
sub fileDetails {
my %fileDetails;
... # assign stuff
return \%fileDetails;
}
When the execution leaves the subroutine, the variable goes out of scope, but the data contained in memory remains.
The reason the Dumper output looks like that is that you are feeding it a referenced list. Subroutines cannot return arrays or hashes, they can only return lists of scalars. What you are doing is something like this:
print Dumper \(qw(something 0 somethingelse 7.123 else burst));
Perl functions can not return hashes, only lists. A return %foo statement will flatten out %foo into a list and returns the flattened list. To get the return value to be interpreted as a hash, you can assign it to a named hash
%new_hash = fileDetailsSub(...);
print Dumper(\%new_hash);
or cast it (not sure if that is the best word for it) with a %{{...}} sequence of operations:
print Dumper( \%{ {fileDetailsSub(...)} } );
Another approach, as TLP points out, is to return a hash reference from your function.
You can't return a hash directly, but perl can automatically convert between hashes and lists as needed. So perl is converting that into a list, and you are capturing it as a list. i.e.
Dumper( filedetail() ) # list
my %fd = filedetail(); Dumper( \%fd ); #hash
In list context, Perl does not distinguish between a hash and a list of key/value pairs. That is, if a subroutine returns a hash, what it really returns is an list of (key1, value1, key2, value2...). Fortunately, that works both ways; if you take such a list and assign it to a hash, you get a faithful copy of the original:
my %fileDetailsCopy = subroutineName();
But if it wouldn't break other code, it would probably make more sense to have the sub return a reference to the hash instead, as TLP said.

Perl: function returns reference or copy?

Im a newbie in perl. So the question might sound something naive.
I have two following functions
#This function will return the reference of the array
sub getFruits1
{
my #fruits = ('apple', 'orange', 'grape');
return \#fruits;
}
But in the following case?
#How it returns?
sub getFruits2
{
my #fruits = ('apple', 'orange', 'grape');
return #fruits;
}
Will getFruits2 return a reference and a new copy of that array will be created?
The getFruits2 subroutine returns a list, which can be assigned to a new array like this
my #newfruits = getFruits2();
And yes, it will produce a copy of the data in the array
getFruits1 will return a reference to an array. The \ creates a reference.
getFruits2 will return a list of the values in #fruits. It won't return a reference. You'll only get a copy of the array if you assign the return value to an array.
getFruits1 returns a reference.No new array is created.
getFruits2 returns a list
An example of Perl referencing
#!/usr/bin/perl -w
use strict;
my #array = ('a','b','c');
printf("[%s]\n",join('',#array));
my $ref=\#array;
${#{$ref}}[0]='x'; # Modifies #array using reference
printf("[%s]\n",join('',#array));
The only thing that can be returned by a sub is a list of scalars. Arrays can't be returned.
\#fruits
evaluates to a reference, so
return \#fruits;
returns a reference. In list context,
#fruits
evaluates to a list of the elements of #fruits, so
return #fruits;
returns a list of the elements of #fruits if the sub is evaluated in list context.