Retrieve a particular return value in Perl - perl

I'm looking for a one-liner that lets me grab the second return value from a subroutine.
Rather than this:
($a,$b)=function;
print $b
It should be possible to do something like this
print ??? function

This works:
sub test { return (1,2) }
print ((test)[1]); # Returns 2
This also works:
print +(func())[1], "\n";

assuming that function() returns a list, then using a slice like the poster above suggested works just fine. If it returns an array reference, then you need to access it appropriately, for instance (#{function()})[1] to dereference the aref and then slice it.

Related

what is the best way to assign a value inside a nested hash?

My code constructs a hash %oprAtnNOW that contains a hash ref, where both the keys and values inside
$oprAtnNOW{opt} are determined at run time.
The sample code below demonstrates that a single command suffices to extract a value from the anonymous hash referenced by $oprAtnNOW{opt}.
But assigning a value doesn't work like that.
When I try to assign the string wolf to the key Dog, something very strange happens.
When I use Dumper to look at the result, it appears that the value assigned was 'wolf, with a single quote pasted to the start of the string;
and when I use print to look at it, it looks like SCALAR(something).
(The end of my code demonstrates that 'wolf does not print out as SCALAR(something), so Dumper has something else in mind.)
So my sample code contains a workaround:
deference the anonymous inner hash; assign key and value in the now named, temporary hash; clobber the previous $oprAtnNOW{opt}
with a reference to the temporary, named hash.
Why does the direct method yield such a strange result?
What is the true content of this SCALAR thing?
Is there a way to do this with a single command, without my multi-step workaround?
#!/usr/bin/perl
use strict; use warnings;
use Data::Dumper qw(Dumper);
$Data::Dumper::Sortkeys = 1;
my %oprAtnNOW;
${$oprAtnNOW{opt}{Dog}} = 'wolf';
print Dumper {%oprAtnNOW};
print join('', '$oprAtnNOW{opt}{Dog}==', $oprAtnNOW{opt}{Dog}, "\n",);
{
my %tmp_oprAtnNOW_opt = %{$oprAtnNOW{opt}} if(defined $oprAtnNOW{opt});
$tmp_oprAtnNOW_opt{Dog} = 'wolf'; # will clobber any previous value for Dog
$oprAtnNOW{opt} = {%tmp_oprAtnNOW_opt};
}
print Dumper {%oprAtnNOW};
print join('', '$oprAtnNOW{opt}{Dog}==', $oprAtnNOW{opt}{Dog}, "\n",);
my $teststring = join('', "\x27", 'wolf',);
print "teststring==$teststring\n";
You want
$oprAtnNOW{opt}{Dog} = 'wolf';
$BLOCK = EXPR; expects BLOCK to return a reference to a scalar.
Thanks to autovivification, one is created for you if needed. In other words,
${$oprAtnNOW{opt}{Dog}} = 'wolf';
is short for
${ $oprAtnNOW{opt}{Dog} //= \my $anon } = 'wolf';
which could also be written as
my $anon = 'wolf';
$oprAtnNOW{opt}{Dog} = \$anon;
This is not what you want. You don't want to assign a reference to the hash; you want to assign the string wolf. To achieve that, you can use
$oprAtnNOW{opt}{Dog} = 'wolf';
This short for
$oprAtnNOW{opt}->{Dog} = 'wolf';
aka
${ $oprAtnNOW{opt} }{Dog} = 'wolf';
The latter is of the form
$BLOCK{Dog} = 'wolf';
which, like $NAME{Dog}, is an assignment to a hash element.

Assign number to variable in perl subroutine [assign returned list to variables]

I am trying to call a multiple variable from a subroutine but when i try to print, it just print only one variable.
In python the script will be f=mode()[0] and b=mode()[1] and it works.
subroutinefile a.pl
sub mode() {
my ($f, $b);
$f=41;
$b=2;
return ($f,$b);
}
And another file that calls the a.pl
use strict;
use warnings;
require 'a.pl';
my ($f,$b);
$f= mode(0);
$b= mode(1);
print "$f\n";
print "$b\n";
The problem is it only prints 2 for both f and b.
You have passed arguments to subroutine: $f = mode(0); $b = mode(1);.
Try the following:
my ($f,$b) = mode();
Your subroutine returns a fixed length list. You may assign values in the list to your variables.
The problem is the mismatch between the definition of the subroutine (no parameters) and the way you are trying to call it (one argument).
Change those calls to this and it works:
$f= (mode())[0];
$b= (mode())[1];
Think there is a syntactical difference between getting an array index FROM the return set versus sending an argument; function(xxx) sends the argument, (function()[])is using an array slice of the return.

perl call subroutine to generate random strings not working

The script to generate random strings:
sub rand_Strings {
my #chars = ("A".."Z", "a".."z", "0".."9");
my $string;
$string .= $chars[rand #chars] for 1..8;
}
my $strings = &rand_Strings;
print $strings;
However, it works when it is not in a subroutine. And also works if the $string is a global variable. What did I miss? Thanks,
You need to explicitly add a return statement inside your subroutine.
The automatic return of the last statement inside a subroutine does not work inside a loop construction, which in your example is a for loop.
The postfix version of the for loop is equivalent to the regular version with curly braces.
From perldoc perlsub:
If no "return" is found and if the last statement is an expression, its
value is returned. If the last statement is a loop control structure like
a "foreach" or a "while", the returned value is unspecified. The empty sub
returns the empty list.

perl, function only printing first element of the array

I have an array that has several elements on it but when I pass the array as a parameter to a function and then call the function it only prints out the first element of the array multiple times. For example
my $element;
my $random_variable = "Testing";
my #the_array = ("hello", "bye", "hey");
foreach $element(#the_array)
{
PrintFunction(#the_array, $random_variable)
}
sub PrintFunction{
my ($the_array, $random_variable) = #_;
// other code here
print $the_array . "\n";
}
The result I get from this is
hello
hello
hello
The result I want is to print all the elements of the array as
hello
bye
hey
Change:
PrintFunction(#the_array, $random_variable)
to:
PrintFunction($element, $random_variable)
Your code passes the entire array to the sub, then you only print the 1st element of the array each time because you use the scalar variable $the_array inside the sub. Since foreach grabs each element of the array, you probably meant to use $element.
Add Print #_; to your sub to see what is passed to it. You will see:
hellobyeheyTesting
hellobyeheyTesting
hellobyeheyTesting
It means you are passing the entire array followed by the $random_variable. Therefore, $the_arrayin the sub will be always the first elements of #the_array which is hello. To fix that, you should pass each element of array iteratively by
foreach $element(#the_array)
{
PrintFunction(#element, $random_variable)
}

How can I iterate over a Perl array reference?

I have an array that is a member of a structure:
$self->{myArray} = ["value1", "value2"];
And I'm trying to iterate over it using the following code:
my #myArray = $self->{myArray};
foreach my $foo (#myArray){
#Do something with the using $foo
...
}
The problem is that the 'foreach' loop is executed only once (when I would expect it to execute twice, since #myArray has two elements: "value1" and "value2").
When I check the #myArray array size, I get that its size is 1. What am I doing wrong in this code?
I believe that:
$self->{myArray} returns a reference.
You want to return the array:
#{$self->{myArray}}
$self->{myArray} is an array reference. You need to dereference it.
my #myArray = #{ $self->{myArray} };
In situations like this, the Data::Dumper module is very helpful. For example, if #myArray were not behaving as expected, you could run this code to reveal the problem.
use Data::Dumper;
print Dumper(\#myArray);
$self->{myArray} is an array reference, not an array - you can't store actual arrays inside a hash, only references. Try this:
my $myArray = $self->{myArray};
for my $foo (#$myArray){
# do something with $foo
}
You also may want to have a look at perldoc perlref.