I'm quite new to perl and I can't seem to find any information on how one would know if a subroutine takes a parameter.
In other languages (e.g python, java, etc), it is very clear, a method/function usually looks like this:
def my_func(arg1, arg2):
# do something
But in perl, it's simply:
sub my_func {
my params = #_;
# do something
}
But I've seen examples where my params = #_ isn't even included, but the subroutine is called and passed an argument.
e.g
sub my_func {
my $self = shift;
my $fieldstr = 'tbl'.$self->db_func.'*,';
my $sql = "SELECT $fieldstr FROM tbl".$self->db_func.'WHERE'.$self->...;
my $sth = $self->other_func->my_func($sql) or return undef;
}
So I was wondering if there is some sort of guideline to know if a subroutine takes a parameter(s)?
Please take a look at my answer to a similar question.
Perl is hyper-flexible, in that a subroutine can simply ignore excess parameters, provide defaults for missing ones, or die if the parameters aren't exactly what is expected.
Perl's author, Larry Wall, is a linguist, and the rationale behind this is that subroutines behave like imperative verbs; so just as you could say "fetch the wood", "fetch the wood from behind the shed", or "fetch the wood from behind the shed using the tractor", you can equally say
fetch($wood)
fetch($wood, $shed)
fetch($wood, $shed, $tractor)
or even
fetch($wood, {from => 'shed', using => 'tractor'})
and it is up to the subroutine to work out what is required.
Subroutine prototypes should be avoided, as they have side-effects that change the behaviour of the code in ways that aren't obvious. They are intended only for writing additional language constructs; a good example is Try::Tiny.
Arguments are passed in #_, so you'd need to look for uses of #_. For example,
my ($x, $y) = #_;
shift in a sub is the same as shift(#_)
$_[$i]
&f (but not &f()), as in sub log_warn { unshift #_, 'warn'; &log }
As a sub writer, you should use these as near the top of the sub as possible to make them obvious. The last two are usually used as optimizations or to have by-reference parameters.
The parameters for a subroutine call are contained in the array #_.
Two important functions for array manipulation are shift and pop. Suppose you have a list (1, 2, 3, 4).
shift removes a value from the left side of the list and returns it.
my #list = ( 1, 2, 3, 4 );
my $value = shift #list;
print "$value\n"; # will print "1"
print "#list\n"; # will print "2 3 4"
pop does the same thing from the right side instead of the left:
my #list = ( 1, 2, 3, 4 );
my $value = pop #list;
print "$value\n"; # will print "4"
print "#list\n"; # will print "1 2 3"
When used inside a subroutine, pop and shift will use the #_ array by default:
some_function( 'James', 99 ); #these 2 arguments will be passed to the function in "#_"
sub some_function {
my $name = shift; #remove 'James' from list #_ and store it in $name
my $age = shift; #remove 99 from list #_ and store it in $age
print "Your name is $name and your age is $age\n";
}
Related
(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) } );
}
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.
Another Perl-beginner question, but strangely enough, I found no tutorial to explain me this simple problem.
I wanted, as an exercise, to write a function map that takes a function and an array, returning an array. In functional languages, this is used quite often and I heard about the sub references and how to use them.
sub map {
my $f = shift;
my #r = ();
foreach (#_) {
push(#r, &f($_));
}
return #r;
}
sub square {
my $r = shift;
return $r*$r;
}
print map(\&shift, 1, 2, 3, 4, 5);
But, for some reason, I only get the word CODE and a hex-number as an output, five times. I have then changed the call of f in map, to $$f($_) and $f->($_) but all of it had the same result.
What do I do wrong here?
perl have a builin map function. let's call it map2
use &$f to dereference $f
use join to print an array properly
sub map2 {
my $f = shift;
my #r = ();
foreach (#_) {
push(#r, &$f($_));
}
return #r;
}
sub square {
my $r = shift;
return $r*$r;
}
print join ",", map2(\&square, 1, 2, 3, 4, 5);
$ perl 1.pl
1,4,9,16,25
As mentioned in comments, Perl has a built in map function that you should use.
my #squares = map {$_ ** 2} 1 .. 5;
Rather than passing an argument, Perl's built in map sets $_ to each element, which allows you to write your square function succinctly as either {$_ * $_} or {$_ ** 2}
But Perl also gives you the ability to make custom map-like functions with a similar syntax. For example, say you wanted to write a version of map that maps over pairs of values:
sub pair_map (&#) { # the (&#) prototype here tells perl that the sub
my $code = shift; # takes a code block, and then a list, just like `map`
my #ret;
while (#_) {
push #ret, $code->(splice #_, 0, 2);
}
#ret
}
my #pairs = pair_map {\#_} 1 .. 10;
pair_map {print "$_[0]: $_[1]\n"} %hash;
But since Perl has been around a while, most utility functions have probably been written already. A search of CPAN will turn up many map-like functions that do various things.
I found that I frequently need to map over lists with various step sizes, so I wrote the mapn function in List::Gen. This is a fully developed solution, so it includes an optimization when called in void context, and falls back to Perl's own map when n == 1:
sub mapn (&$#) {
my ($sub, $n, #ret) = splice #_, 0, 2;
croak '$_[1] must be >= 1' unless $n >= 1;
return map $sub->($_) => #_ if $n == 1;
my $want = defined wantarray;
while (#_) {
local *_ = \$_[0];
if ($want) {push #ret =>
$sub->(splice #_, 0, $n)}
else {$sub->(splice #_, 0, $n)}
}
#ret
}
Both pair_map and mapn utilize an advanced feature of Perl subroutines called prototypes. These prototypes are not argument validation tools (like in many other languages). Rather, they tell perl to interpret calls to the functions in a special way (similar to the way some other builtin functions are used). In this case, the & portion of the prototype tells perl that the first argument to these functions can be written as a bare block, just like a normal map call.
What syntax, if any, is able to take a reference of a builtin like shift?
$shift_ref = $your_magic_syntax_here;
The same way you could to a user defined sub:
sub test { ... }
$test_ref = \&test;
I've tried the following, which all don't work:
\&shift
\&CORE::shift
\&{'shift'}
\&{'CORE::shift'}
Your answer can include XS if needed, but I'd prefer not.
Clarification: I am looking for a general purpose solution that can obtain a fully functional code reference from any builtin. This coderef could then be passed to any higher order function, just like a reference to a user defined sub. It seems to be the consensus so far that this is not possible, anyone care to disagree?
No, you can't. What is the underlying problem you are trying to solve? There may be some way to do whatever that is.
Re the added part of the question "Your answer can include XS if needed, but I'd prefer not.",
calling builtins from XS is really hard, since the builtins are set up to assume they are running as part of a compiled optree and have some global variables set. Usually it's much easier to call some underlying function that the builtin itself uses, though there isn't always such a function, so you see things like:
buffer = sv_2mortal(newSVpvf("(caller(%d))[3]", (int) frame));
caller = eval_pv(SvPV_nolen(buffer), 1);
(doing a string eval from XS rather than go through the hoops required to directly call pp_caller).
I was playing around with general purpose solutions to this one, and came up with the following dirty hack using eval. It basically uses the prototype to pull apart #_ and then call the builtin. This has only been lightly tested, and uses the string form of eval, so some may say its already broken :-)
use 5.10.0;
use strict;
use warnings;
sub builtin {
my ($sub, $my, $id) = ($_[0], '');
my $proto = prototype $sub //
prototype "CORE::$sub" //
$_[1] //
($sub =~ /map|grep/ ? '&#' : '#;_');
for ($proto =~ /(\\?.)/g) { $id++;
if (/(?|(\$|&)|.(.))/) {
$my .= "my \$_$id = shift;";
$sub .= " $1\$_$id,";
} elsif (/([#%])/) {
$my .= "my $1_$id = splice \#_, 0, \#_;";
$sub .= " $1_$id,";
} elsif (/_/) {
$my .= "my \$_$id = \#_ ? shift : \$_;";
$sub .= " \$_$id,"
}
}
eval "sub ($proto) {$my $sub}"
or die "prototype ($proto) failed for '$_[0]', ".
"try passing a prototype string as \$_[1]"
}
my $shift = builtin 'shift';
my #a = 1..10;
say $shift->(\#a);
say "#a";
my $uc = builtin 'uc';
local $_ = 'goodbye';
say $uc->('hello '), &$uc;
my $time = builtin 'time';
say &$time;
my $map = builtin 'map';
my $reverse = builtin 'reverse';
say $map->(sub{"$_, "}, $reverse->(#a));
my %h = (a=>1, b=>2);
my $keys = builtin 'keys';
say $keys->(\%h);
# which prints
# 1
# 2 3 4 5 6 7 8 9 10
# HELLO GOODBYE
# 1256088298
# 10, 9, 8, 7, 6, 5, 4, 3, 2,
# ab
Revised with below and refactored.
You could do this if you patched the internal method first (which would give you the coderef of your patch):
use strict;
use warnings;
BEGIN {
*CORE::GLOBAL::die = sub { warn "patched die: '$_[0]'"; exit 3 };
}
print "ref to patched die: " . \&CORE::GLOBAL::die . "\n";
die "ack, I am slain";
gives the output:
ref to patched die: CODE(0x1801060)
patched die: 'ack, I am slain' at patch.pl line 5.
BTW: I would appreciate if anyone can explain why the override needs to be done as *CORE::GLOBAL::die rather than *CORE::die. I can't find any references for this. Additionally, why must the override be done in a BEGIN block? The die() call is done at runtime, so why can't the override be done at runtime just prior?
You can wrap shift with something that you can reference, but you have to use a prototype to use it, since shift is special.
sub my_shift (\#) { my $ll = shift; return shift #$ll }
The problem is that the prototype system can't magically figure out that when it calls some random ref-to-sub in a scalar, that it needs to take the reference before calling the subroutine.
my #list = (1,2,3,4);
sub my_shift (\#) { my $ll = shift; return shift #$ll }
my $a = shift #list;
my $my_shift_ref = \&my_shift;
my $b = (&{$my_shift_ref} (\#list) ); # see below
print "a=$a, b=$b\n";
for (my $i = 0; $i <= $#list; ++$i) { print "\$list[$i] = ",$list[$i],"\n"; }
If this is called as just #list, perl barfs, because it can't automagically make references the way shift does.
See also: [http://www.perl.com/language/misc/fmproto.html][Tom Christensen's article].
Of course, for builtins that aren't special like shift, you can always do
sub my_fork { return fork; }
and then &my_fork all you want.
As I understand you want to have coderef that will be called on some data, and it might point to some your function or to builtin.
If I'm right, just put the builtin in closure:
#!/usr/bin/perl -w
use strict;
my $coderef = \&test;
$coderef->( "Test %u\n", 1 );
$coderef = sub { printf #_ };
$coderef->( "Test %u\n", 2 );
exit;
sub test {
print join(' ', map { "[$_]" } #_) . "\n";
}
Doing it with shift is also possible, but remember that shift without explicit array to work on, works on different arrays based on where it was called.
If you want to see what it takes to fake it in production quality code, look at the code for autodie. The meat is in Fatal. Helps if you're a mad pirate Jedi Australian.
The only way I can get it to work is to make a reference to sub{shift}.
perl -e '#a=(1..3); $f=sub{shift}; print($f->(#a), "\n");'
This is functionally equivalent to:
perl -e '#a=(1..3); print(shift(#a), "\n");'
Which could be just perl -e 'print 1, "\n"' but then we wouldn't be talking about a builtin.
For your information I'm surprised that one cannot reference a builtin, and now that it's been made clear to me I can't help but think of it as a deficiency in Perl.
Update Eric correctly points out that $f=sub{shift}; $f->(#a) leaves #a unchanged. It should be more like:
perl -e '#a=(1..3); $f=sub{shift #{+shift}}; print($f->(\#a), "\n");
Thanks Eric.
I have a function that takes a variable and an associative array, but I can't seem to get them to pass right. I think this has something to do with function declarations, however I can't figure out how they work in Perl. Is there a good reference for this and how do I accomplish what I need?
I should add that it needs to be passed by reference.
sub PrintAA
{
my $test = shift;
my %aa = shift;
print $test . "\n";
foreach (keys %aa)
{
print $_ . " : " . $aa{$_} . "\n";
$aa{$_} = $aa{$_} . "+";
}
}
Pass the reference instead of the hash itself. As in
PrintAA("abc", \%fooHash);
sub PrintAA
{
my $test = shift;
my $aaRef = shift;
print $test, "\n";
foreach (keys %{$aaRef})
{
print $_, " : ", $aaRef->{$_}, "\n";
}
}
See also perlfaq7: How can I pass/return a {Function, FileHandle, Array, Hash, Method, Regex}?
This code works:
#!/bin/perl -w
use strict;
sub PrintAA
{
my($test, %aa) = #_;
print $test . "\n";
foreach (keys %aa)
{
print $_ . " : " . $aa{$_} . "\n";
}
}
my(%hash) = ( 'aaa' => 1, 'bbb' => 'balls', 'ccc' => \&PrintAA );
PrintAA("test", %hash);
The key point is the use of the array context in the my() 'statement' in the function.
What does the array context business actually do?
Succinctly, it makes it work correctly.
It means that the first value in the #_ array of arguments is assigned to $test, and the remaining items are assigned to the hash %aa. Given the way I called it, there is an odd number of items in the #_, so once the first item is assigned to $test, there is an even number of items available to assign to %aa, with the first item of each pair being the key ('aaa', 'bbb', 'ccc' in my example), and the second being the corresponding value.
It would be possible to replace %aa with #aa, in which case, the array would have 6 items in it. It would also be possible to replace %aa with $aa, and in that case, the variable $aa would contain the value 'aaa', and the remaining values in #_ would be ignored by the assignment.
If you omit the parentheses around the variable list, Perl refuses to compile the code.
One of the alternative answers showed the notation:
my $test = shift;
my(%aa) = #_;
This is pretty much equivalent to what I wrote; the difference is that after the two my statements, #_ only contains 6 elements in this variation, whereas in the single my version, it still contains 7 elements.
There are definitely other questions in SO about array context.
Actually, I wasn't asking about the my($test, %aa) = #_; I was asking about my(%hash) = ( 'aaa' => 1, 'bbb' => 'balls', 'ccc' => \&PrintAA ); versus my %hash = { 'aaa' => 1, ... };
The difference is that the { ... } notation generates a hash ref and the ( ... ) notation generates a list, which maps to a hash (as opposed to hash ref). Similarly, [ ... ] generates an array ref and not an array.
Indeed, change the 'main' code so it reads: my(%hash) = { ... }; and you get a run-time (but not compile time) error - treat line numbers with caution since I've added alternative codings to my file:
Reference found where even-sized list expected at xx.pl line 18.
...
Use of uninitialized value in concatenation (.) or string at xx.pl line 13.
Alternatively:
sub PrintAA
{
my $test = shift;
my %aa = #_;
print $test . "\n";
foreach (keys %aa)
{
print $_ . " : " . $aa{$_} . "\n";
$aa{$_} = $aa{$_} . "+";
}
}
The thing you're fundamentally missing is that an associative array isn't a single argument (though an associative array reference is, as in Paul Tomblin's answer).
It looks like you should pass in a reference to a hash.
sub PrintAA
{
my $test = shift;
my $aa = shift;
if (ref($aa) != "HASH") { die "bad arg!" }
....
}
PrintAA($foo, \%bar);
The reason you can't do a
my %aa = shift;
is because Perl flattens all the arguments to a subroutine into one list, #_. Every element is copied, so passing in by reference avoids those copies as well.
As usual there are several ways. Here is what Perl Best Practices, that most revered of style pointers, has to say about passing parameters to functions:
Use a hash of named arguments for any subroutine that has more than three parameters
But since you have only two, you could get away ;) with passing them directly like this:
my $scalar = 5;
my %hash = (a => 1, b => 2, c => 3);
func($scalar, %hash)
And function is defined like this:
sub func {
my $scalar_var = shift;
my %hash_var = #_;
... Do something ...
}
It could be more useful if you could show some code.
All the methods in previous answers work, but this was always the way I preferred to do things like this:
sub PrintAA ($\%)
{
my $test = shift;
my %aa = ${shift()};
print "$test\n";
foreach (keys %aa)
{
print "$_ : $aa{$_}\n";
$aa{$_} = "$aa{$_}+";
}
}
Note: I also changed your code a bit. Perl's double-quoted strings will interpret "$test" to be the value of $test rather than the actual string '$test', so you don't need that many .s.
Also, I was wrong about how the prototypes work. To pass a hash, use this:
PrintAA("test", %hash);
To print a hash reference, use this:
PrintAA("test", %$ref_to_hash);
Of course, now you can't modify the hash referenced by $ref_to_hash because you're sending a copy, but you can modify a raw %hash because you're passing it as a reference.
Arguments to functions get flattened into a single array (#_). So it's usually easiest to pass hashes to a function by reference.
To create a hash:
my %myhash = ( key1 => "val1", key2 => "val2" );
To create a reference to that hash:
my $href = \%myhash
To access that hash by reference;
%$href
So in your sub:
my $myhref = shift;
keys %$myhref;
All the other replies here so far seem rather complicated to me. When I write Perl function I usually "expand" all the passed arguments in the first line of the function.
sub someFunction {
my ( $arg1, $arg2, $arg3 ) = #_;
This is similar to other languages, where you declare functions as
... someFunction ( arg1, arg2, arg3 )
And if you do it that way and pass the hash as the last argument, you'll be fine without any tricks or special magic. E.g.:
sub testFunc {
my ( $string, %hash ) = #_;
print "$string $hash{'abc'} $hash{'efg'} $string\n";
}
my %testHash = (
'abc' => "Hello,",
'efg' => "World!"
);
testFunc('!!!', %testHash);
The output is as expected:
!!! Hello, World! !!!
This works because in Perl arguments are always passed as an array of scalar values and if you pass a hash, its key value/pairs are added to that array. In the sample above, the arguments passed to the function as array (#_) are in fact:
'!!!', 'abc', 'Hello,', 'efg', 'World!'
and '!!!' is simply assigned to %string, while %hash "swallows" all the other arguments, always interpreting one as a key and the next one as value (until all elements are used up).
You cannot pass multiple hashes that way and the hash cannot be the first argument, as otherwise it would swallow everything and leave all other arguments unassigned.
Of course, exactly the same works for array as a last argument. The only difference here is that arrays don't distinguish between keys and values. For them, all arguments left over are values and just get pushed to the array.
Use the following sub to get the hash or hashref - whatever is passed :)
sub get_args { ref( $_[0] ) ? shift() : ( #_ % 2 ) ? {} : {#_}; }
sub PrintAA
{
my $test = shift;
my $aa = get_args(#_);;
# Then
$aa->{somearg} # Do something
$aa->{anotherearg} # Do something
}
Call your function like this:
printAA($firstarg,somearg=>1, anotherarg=>2)
Or like this (no matter):
printAA($firstarg, {somearg=>1, anotherarg=>2})
Or even like this (no matter):
my(%hash) = ( 'aaa' => 1, 'bbb' => 'balls', 'ccc' => \PrintAA );
PrintAA("test", %hash);