How can I pass two lists to a Perl subroutine? - perl

Is it possible to pass two lists to a sub in Perl, for example:
sub Foo {
my(#list1,#list2) = #_;
}
I know I could make #_ two lists, with each sublist being the desired argument, I'm just wondering if there is a cleaner way

Well if you want two arrays you could use a prototype:
sub foo (\#\#) {
my $arr1 = shift;
my $arr2 = shift;
# Access arrays as references
}
foo( #wiz, #waz ); # #wiz and #waz won't be flattened.
But there are many ways to get around prototypes, and I prefer to avoid them in most places. You can simply skip the prototype and manually pass references:
sub foo {
my $arr1 = shift;
my $arr2 = shift;
# Access arrays as references
}
foo( \#wiz, \#waz ); # Pass in wiz/waz as refs
foo( [1,2,4],[3,5,6] ); # Hard coded arrays
If you haven't worked with references at all, check out perlreftut for a nice tutorial.

If you pass two lists by value ... you're going to get one big list in #_.
my(#list1,#list2) = #_; doesn't make any sense:
#!/usr/bin/perl
sub test
{
my (#a, #b) = #_;
print "#a\n";
print "#b\n";
}
my #array1 = (1,2,3);
my #array2 = (5,6,7);
test(#array1, #array2);
This will end up printing:
1 2 3 5 6 7
<blank line>
To pass two arrays, you'd need to pass them by reference:
test(\#array1, \#array2);
And in your sub you'd need to treat them as references:
sub test
{
my ($arrayRef1, $arrayRef2) = #_;
print "#$arrayRef1\n";
print "#$arrayRef2\n";
}

Related

How to pass entire subroutine into hashtable data using perl?

I have the following subroutine which i should pass the routine as hashtable and that hashtable should be again called inside another subroutine using perl?
input file(from linux command bdata):
NAME PEND RUN SUSP JLIM JLIMR RATE HAPPY
achandra 0 48 0 2000 50:2000 151217 100%
agutta 1 5 0 100 50:100 16561 83%
My subroutine:
sub g_usrs_data()
{
my($lines) = #_;
my $header_found = 0;
my #headers = ();
my $row_count = 0;
my %table_data = ();
my %row_data = ();
$lines=`bdata`;
#print $lines;
foreach (split("\n",$lines)) {
if (/NAME\s*PEND/) {
$header_found = 1;
#headers =split;
}
elsif (/^\s*$/)
{
$header_found=0;
}
$row_data{$row_count++} = $_;
#print $_;
}
My query:
How can i pass my subroutine as hash into another subroutine?
example:
g_usrs_data() -> this is my subroutine .
the above subroutine should be passed into another subroutine (i.e into usrs_hash as hash table)
example:
create_db(usrs_hash,$sql1m)
Subroutines can be passed around as code references. See perlreftut and perlsub.
An example with an anonymous subroutine
use warnings;
use strict;
my $rc = sub {
my #args = #_;
print "\tIn coderef. Got: |#_|\n";
return 7;
}; # note the semicolon!
sub use_rc {
my ($coderef, #other_args) = #_;
my $ret = $coderef->('arguments', 'to', 'pass');
return $ret;
}
my $res = use_rc($rc);
print "$res\n";
This silly program prints
In coderef. Got: |arguments to pass|
7
Notes on code references
The anonymous subroutine is assigned to a scalar $rc, making that a code reference
With an existing (named) sub, say func, a code reference is made by my $rc = \&func;
This $rc is a normal scalar variable, that can be passed to subroutines like any other
The sub is then called by $rc->(); where in parenthesis we can pass it arguments
Note that the syntax for creating and using them are just like for other data types
As anonymous assign by = sub { }, much like = [ ] (arrayref) and = { } (hashref)
For a named sub use & instead of a sigil, so \& for sub vs. \# (array) and \% (hash)
They are used by ->(), much like ->[] (arrayref) and ->{} (hashref)
For references in general see perlreftut. Subroutines are covered in depth in perlsub.
See for example this post on anonymous subs, with a number of answers.
For far more see this article from Mastering Perl and this article from The Effective Perler.

Perl: Sub's arguments explain

In perl all sub's argument writting to #_ array, like this:
call_any_sub($a,$b,$c);
sub call_any_sub {
my $s_a = shift;
my $s_b = shift;
my $s_c = shift;
}
But, if i want to passed array as an argument to sub, i should use:
call_any_sub(#data_array);
sub call_any_sub {
my #data = #_;
}
Instead of similar:
call_any_sub(#data_array);
sub call_any_sub {
my #data = shift;
}
So, why #data_array replaces the array of arguments and not written in it (as expected)?
One can only pass a list of scalars to a subroutine (and that's all they can return). After all, the arguments are presented to the sub as an array (#_), and arrays can only contains scalars.
You can either (inefficiently) recreate the array in the sub
sub foo {
my #bars = #_;
say for #bars;
}
foo(#bars);
or you can pass a reference to the array
sub foo {
my ($bars) = #_;
say for #$bars;
}
foo(\#bars);
You need to understand what shift does.
The shift/unshift pair of commands are parallel to the pop/push pair of commands. All of these commands operate on arrays. By default, shift (and only shift) assumes the #_ array when called in a subroutine and #ARGV when called in the main program. This means the following two statements are identical in a subroutine:
my $foo = shift #_; # Explicit Argument
my $foo = shift # Implicit Argument
Perl's parameter passing is an interesting concept because it doesn't really do named parameter passing like almost all other programs. Instead, everything is passed as one long list of scalars. This makes it hard when you aren't passing in a scalar.
It works okay if I am only passing in a single hash or array:
munge_hash ( %foo );
sub munge_hash {
my %hash = #_;
...
}
And, you have to be careful if you're passing in multiple arguments and an array. In this case, the array must be the last in your list of arguments:
my $foo = "floop";
my $bar = "bloop";
my #array = qw(loop coop soop);
munge_this ( $foo, $bar, #array );
sub munge_this {
say join ":", #_; # Prints "floop:bloop:loop:coop:soop"
my $var1 = shift # floop
my $var2 = shift # bloop
my #arry = #_ # The rest is the array passed.
However, things really fall apart if you're passing in multiple arrays or hashes. All of the elements get merged into a single list of scalars represented by #_.
munge_two_arrays ( #foo, #bar );
sub munge_two_arrays {
# Problem! Elements of both arrays are in #_.
# How do I separate them out?
}
Thus, it is common not to pass in a whole array, but an array reference:
munge_two_arrays( \#foo, \#bar ); # These are array references
sub munge_two_arrays {
my $array1_ref = shift;
my $array2_ref = shift;
my #array1 = #{ $array1_ref } # Dereference array references to make arrays
my #array2 = #{ $array2_ref } # Dereference array references to make arrays
}
This keeps the values of the two arrays from getting merged into a single #_.

Assigning multiple Values to a hash Reference - Array

i declared the following sub (In reality, the values come out of the Database - so i simplified it):
sub get_date {
my ($ref_last)=#_;
$$ref_last->{duration}='24,0,4';
($$ref_last->{duration}->{d},
$$ref_last->{duration}->{h},
$$ref_last->{duration}->{m})
= split(/\,/, $$ref_last->{duration});
}
This sub is called from the main-Part of the script, like this:
my $hashy;
get_date(\$hashy);
print $hashy->{duration}->{d};
Everything ist fine, and works like a charm, until i use strict:
use strict;
my $hashy;
get_date(\$hashy);
print $hashy->{duration}->{d};
in this case perl says "Can't use string ("24,0,4") as a HASH ref while "strict refs" in use"
I already tried ref($ref_last) - but ref is a read-only function.
Any suggestions, why this happens - and perhaps a better solution ?
Here's the full (non)-Working script:
#!/usr/bin/perl -w
use strict;
my $hashy;
get_date(\$hashy);
print $hashy->{duration}->{d};
sub get_date {
my ($ref_last)=#_;
$$ref_last->{duration}='24,0,4';
($$ref_last->{duration}->{d},
$$ref_last->{duration}->{h},
$$ref_last->{duration}->{m})
= split(/\,/, $$ref_last->{duration});
}
Based on comments, you're trying to change the format of an existing hash value (from «24,0,4» to «{ d=>24, h=>0, m=>4 }»). Here's how I'd do it.
sub split_duration { # Changes in-place.
my ($duration) = #_;
my %split;
#split{qw( d h m )} = split(/,/, $duration);
$_[0] = \%split;
}
my $row = $sth->fetchrow_hashref();
split_duration( $row->{duration} );
or
sub split_duration {
my ($duration) = #_;
my %split;
#split{qw( d h m )} = split(/,/, $duration);
return \%split;
}
my $row = $sth->fetchrow_hashref();
$row->{duration} = split_duration( $row->{duration} );
Explanation of the problem and initial solutions below.
Without strict, 24,0,4 was treated as a hash reference, which means Perl was creating a variable named $24,0,4!!! That's bad, which is why use strict 'refs'; prevents it.
The underlying problem is your attempt to assign two values to $$ref_last->{duration}: a string
'24,0,4'
and a reference to a hash
{ d => 24, h => 0, m => 4 }
It can't hold both. You need to rearrange your data.
I suspect you don't actually use 24,0,4 after you split it, so you could fix the code as follows:
sub get_date {
my ($ref_last)=#_;
my $duration = '24,0,4';
#{ $$ref_last->{duration} }{qw( d h m )} =
split(/,/, $duration);
}
If you need 24,0,4, you can reconstruct it. Or maybe, you can store the combined duration along with d,h,m.
sub get_date {
my ($ref_last)=#_;
my $duration = '24,0,4';
$$ref_last->{duration}{full} = $duration;
#{ $$ref_last->{duration} }{qw( d h m )} =
split(/,/, $duration);
}
Or in a separate elements of the higher up hash.
sub get_date {
my ($ref_last)=#_;
my $duration = '24,0,4';
$$ref_last->{full_duration} = $duration;
#{ $$ref_last->{duration} }{qw( d h m )} =
split(/,/, $duration);
}
Inside get_date, you assign a string to $ref_last->{duration} but then attempt to access it like a hashref. You also have extra dollar signs that attempt to dereference individual values plucked from the hash.
I would write it as
sub get_date {
my($ref_last) = #_;
my $duration = '24,0,4';
#{ $ref_last->{duration} }{qw/ d h m /} = split /\,/, $duration;
}
The last line is a hash slice that allows you to assign values to the d, h, and m keys in a single list-assignment.
In the context of the caller, you need to set up a bit of scaffolding.
my $hashy = {};
get_date($hashy);
Without initializing $hashy to contain a new empty hashref, get_date does all its assignments and then throws away newly-built edifice. This is because when you copy parameters out of #_, you are using pass-by-value semantics.
Perl will accommodate pass-by-reference as well. Perl has a feature known as autovivification where the language builds necessary scaffolding for you on demand. To use that style, you would write
my $hashy;
get_date($hashy);
sub get_date {
my($ref_last) = #_;
my $duration = '24,0,4';
#{ $_[0]->{duration} }{qw/ d h m /} = split(/\,/, $duration);
}
Note the use of $_[0] to directly access the first parameter, which is an alias to $hashy in this case. That is, get_date modifies $hashy directly.
Either way, say we print the contents with
print "[", join("][" => %{ $hashy->{duration} }), "]\n";
in which case the output is some permutation of
[h][0][m][4][d][24]
Building complex data structures with Perl isn’t difficult, but you have to learn the rules.
Perl references and nested data structures, man perlref
Perl Data Structures Cookbook, perldoc perldsc
Manipulating Arrays of Arrays in Perl, perldoc perllol
This happens because you have a weird syntax for your hash reference.
#!/usr/bin/perl -w
use strict;
my $hashref = {};
get_date($hashref);
print $hashref->{duration}->{d};
sub get_date {
my ($ref_last) = #_;
$tmp = '24,0,4';
($ref_last->{duration}->{d},
$ref_last->{duration}->{h},
$ref_last->{duration}->{m})
= split(/,/, $tmp);
}
and in your subroutine use $ref_last->{duration}, without $$.

How to run an anonymous function in Perl?

(sub {
print 1;
})();
sub {
print 1;
}();
I tried various ways, all are wrong...
(sub { ... }) will give you the pointer to the function so you must call by reference.
(sub { print "Hello world\n" })->();
The other easy method, as pointed out by Blagovest Buyukliev would be to dereference the function pointer and call that using the { } operators
&{ sub { print "Hello World" }}();
Yay, I didn't expect you folks to come up with that much possibilities. But you're right, this is perl and TIMTOWTDI: +1 for creativitiy!
But to be honest, I use hardly another form than the following:
The Basic Syntax
my $greet = sub {
my ( $name ) = #_;
print "Hello $name\n";
};
# ...
$greet->( 'asker' )
It's pretty straight forward: sub {} returns a reference to a sub routine, which you can store and pass around like any other scalar. You can than call it by dereferencing. There is also a second syntax to dereference: &{ $sub }( 'asker' ), but I personally prefer the arrow syntax, because I find it more readable and it pretty much aligns with dereferencing hashes $hash->{ $key } and arrays $array->[ $index ]. More information on references can be found in perldoc perlref.
I think the other given examples are a bit advanced, but why not have a look at them:
Goto
sub bar {goto $foo};
bar;
Rarely seen and much feared these days. But at least it's a goto &function, which is considered less harmful than it's crooked friends: goto LABEL or goto EXPRESSION ( they are deprecated since 5.12 and raise a warning ). There are actually some circumstances, when you want to use that form, because this is not a usual function call. The calling function ( bar in the given example ) will not appear in the callling stack. And you don't pass your parameters, but the current #_ will be used. Have a look at this:
use Carp qw( cluck );
my $cluck = sub {
my ( $message ) = #_;
cluck $message . "\n";
};
sub invisible {
#_ = ( 'fake' );
goto $cluck;
}
invisible( 'real' );
Output:
fake at bar.pl line 5
main::__ANON__('fake') called at bar.pl line 14
And there is no hint of an invisible function in the stack trace. More info on goto in perldoc -f goto.
Method Calls
''->$foo;
# or
undef->$foo;
If you call a method on an object, the first parameter passed to that method will be the invocant ( usually an instance or the class name ). Did i already say that TIMTOWTCallAFunction?
# this is just a normal named sub
sub ask {
my ( $name, $question ) = #_;
print "$question, $name?\n";
};
my $ask = \&ask; # lets take a reference to that sub
my $question = "What's up";
'asker'->ask( $question ); # 1: doesn't work
my $meth_name = 'ask';
'asker'->$meth_name( $question ); # 2: doesn't work either
'asker'->$ask( $question ); # 1: this works
In the snippet above are two calls, which won't work, because perl will try to find a method called ask in package asker ( actually it would work if that code was in the said package ). But the third one succeeds, because you already give perl the right method and it doesn't need to search for it. As always: more info in the perldoc I can't find any reason right now, to excuse this in production code.
Conclusion
Originally I didn't intend to write that much, but I think it's important to have the common solution at the beginning of an answer and some explanations to the unusual constructs. I admit to be kind of selfish here: Every one of us could end up maintaining someones code, who found this question and just copied the topmost example.
There is not much need in Perl to call an anonymous subroutine where it is defined. In general you can achieve any type of scoping you need with bare blocks. The one use case that comes to mind is to create an aliased array:
my $alias = sub {\#_}->(my ($x, $y, $z));
$x = $z = 0;
$y = 1;
print "#$alias"; # '0 1 0'
Otherwise, you would usually store an anonymous subroutine in a variable or data structure. The following calling styles work with both a variable and a sub {...} declaration:
dereference arrow: sub {...}->(args) or $code->(args)
dereference sigil: &{sub {...}}(args) or &$code(args)
if you have the coderef in a scalar, you can also use it as a method on regular and blessed values.
my $method = sub {...};
$obj->$method # same as $method->($obj)
$obj->$method(...) # $method->($obj, ...)
[1, 2, 3]->$method # $method->([1, 2, 3])
[1, 2, 3]->$method(...) # $method->([1, 2, 3], ...)
I'm endlessly amused by finding ways to call anonymous functions:
$foo = sub {say 1};
sub bar {goto $foo};
bar;
''->$foo; # technically a method, along with the lovely:
undef->$foo;
() = sort $foo 1,1; # if you have only two arguments
and, of course, the obvious:
&$foo();
$foo->();
You need arrow operator:
(sub { print 1;})->();
You might not even need an anonymous function if you want to run a block of code and there is zero or one input. You can use map instead.
Just for the side effect:
map { print 1 } 1;
Transform data, take care to assign to a list:
my ($data) = map { $_ * $_ } 2;
# ------------------------------------------------------
# perl: filter array using given function
# ------------------------------------------------------
sub filter {
my ($arr1, $func) = #_;
my #arr2=();
foreach ( #{$arr1} ) {
push ( #arr2, $_ ) if $func->( $_ );
};
return #arr2;
}
# ------------------------------------------------------
# get files from dir
# ------------------------------------------------------
sub getFiles{
my ($p) = #_;
opendir my $dir, $p or die "Cannot open directory: $!";
my #files=readdir $dir;
closedir $dir;
#return files and directories that not ignored but not links
return filter \#files, (sub { my $f = $p.(shift);return ((-f $f) || (-d $f)) && (! -l $f) } );
}

Exploring the uses of anonymous subs

I've always been somewhat confused about the purpose and usage of anonymous subs in perl. I understand the concept, but looking for examples and explanations on the value of this practice.
To be clear:
sub foo { ... } # <--- named sub
sub { ... } # <--- anonymous sub
For example:
$ perl -e 'print sub { 1 }'
CODE(0xa4ab6c)
Tells me that sub returns a scalar value. So, I can do:
$ perl -e '$a = sub { 1 }; print $a'
For the same output as above. This of course holds true for all scalar values, so you can load arrays or hashes with anonymous subs.
The question is, how do I use these subs? Why would I want to use them?
And for a gold star, is there any problem which can only be resolved with an anonymous sub?
Anonymous subroutines can be used for all sorts of things.
Callbacks for event handling systems:
my $obj = Some::Obj->new;
$obj->on_event(sub {...});
Iterators:
sub stream {my $args = \#_; sub {shift #$args}}
my $s = stream 1, 2, 3;
say $s->(); # 1
say $s->(); # 2
Higher Order Functions:
sub apply (&#) {
my $code = shift;
$code->() for my #ret = #_;
#ret
}
my #clean = apply {s/\W+/_/g} 'some string', 'another string.';
say $clean[0]; # 'some_string'
Creating aliased arrays:
my $alias = sub {\#_}->(my $x, my $y);
$alias[0]++;
$alias[1] = 5;
say "$x $y"; # '1 5''
Dynamic programming with closures (such as creating a bunch of subroutines that only differ by a small amount):
for my $name (qw(list of names)) {
no strict 'refs';
*$name = sub {... something_with($name) ...};
}
There is no situation where an anonymous subroutine can do anything that a named subroutine can not. The my $ref = sub {...} constructor is equivalent to the following:
sub throw_away_name {...}
my $ref = \&throw_away_name;
without having to bother with deciding on a unique 'throw_away_name' for each sub.
The equivalence also goes the other way, with sub name {...} being equivalent to:
BEGIN {*name = sub {...}}
So other than the name, the code reference created by either method is the same.
To call a subroutine reference, you can use any of the following:
$code->(); # calls with no args
$code->(1, 2, 3); # calls with args (1, 2, 3)
&$code(); # calls with no args
&$code; # calls with whatever #_ currently is
You can even use code references as methods on blessed or unblessed scalars:
my $list = sub {#{ $_[0] }};
say for [1 .. 10]->$list # which prints 1 .. 10
You can use it to create iterators.
use strict;
use warnings;
use 5.012;
sub fib_it {
my ($m, $n) = (0, 0);
return sub {
my $val = ( $m + $n );
$val = 1 unless $val;
($m, $n) = ($n, $val);
return $val;
}
}
my $fibber = fib_it;
say $fibber->() for (1..3); ### 1 1 2
my $fibber2 = fib_it;
say $fibber2->() for (1..5); ### 1 1 2 3 5
say $fibber->() for (1..3); #### 3 5 8
Anonymous subroutines can be used to create closures.
Closure is a notion out of the Lisp world that says if you define an anonymous function in a particular lexical context, it pretends to run in that context even when it's called outside the context.
perlref
What's a closure?
Here's something similar you might have seen before:
#new_list = map { $_ + 1 } #old_list;
And also:
#sorted = sort { $a <=> $b } #unsorted;
Neither of those are anonymous subs, but their behavior can be imitated in your functions with anonymous subs. They don't need the sub keyword because the functions are (essentially) prototyped to have their first argument be a subroutine, and Perl recognizes that as a special case where sub can be left off. (The functions also set the requisite variables to meaningful values before calling the subroutines you provided in order to simplify argument passing, but that's not related.)
You can write your own map-like function:
sub mapgrep (&#) { # make changes and also filter based on defined-ness
my ($func, #list) = #_;
my #new;
for my $i (#list) {
my $j = $func->($i);
push #new, $j if defined $j;
}
}
The magic to make it work with $_ is a bit much to write here - the above version only works for subs that take arguments.
Well I wrote a SAX parser for perl that is event driven. You can pass anonymous subs to the begin/end events on an element.
my $str = "<xml><row><data></data></row></xml>":
my $parser = SAXParser->new();
$parser->when('row')->begin(sub {
my ($element) = #_;
push(#rows, $row);
});
$parser->when('row')->end(sub {
## do something like serialize it or whatever
});
$parser->parse($str);
They are generally used when you want to pass a sub to another bit of code. Often this is a case of "When X happens (in third party code) do Y".
For example. When defining an attribute in Moose, you can specify the default value of that attribute using a sub. Given a class which has, as part of its definition:
has 'size' => (
is => 'ro',
default =>
sub { ( 'small', 'medium', 'large' )[ int( rand 3 ) ] },
predicate => 'has_size',
);
Whenever an instance of that class is created without an explicit size being passed, the sub will be called and the return value will be the size for that object.
If we switch to another language to give a different example, you'll find a similar concept in JavaScript.
var b = document.getElementById('my_button').
b.addEventListener('click', function (e) { alert('clicked!'); });
In your example, you haven't actually called created subroutine. Call is performed with either &$a or $a->() syntax. What you've done is that you stored a reference to subroutine in $a, then stringifyed it and printed result. Compare:
my $a = sub {1};
my $b = sub {1};
print join("\n", $a, $a->(), $b, $b->());
These are subs for the lazy programmer. You can use them for local throw-away functions and can save some typing. Instead of
sub x { ... }
my $function_ptr = \&x;
you can now use
my $function_ptr = sub { ... };
The anonymous functions are also private, and can only be accessed through the $function_ptr, so they don't have an entry in the symbol table.