Passing a Function Object and Calling it - perl

How do I pass a function, a, to function, b, and have b call a in Perl?

Here's a complete, working script that demonstrates what you're asking.
sub a { print "Hello World!\n"; }
sub b {
my $func = $_[0];
$func->();
}
b(\&a);
Here's an explanation: you take a reference to function a by saying \&a. At that point you have a function reference; while normally a function would be called by saying func() you call a function reference by saying $func->()
The -> syntax deal with other references as well. For example, here's an example of dealing with array and hash references:
sub f {
my ($aref, $href) = #_;
print "Here's an array reference: $aref->[0]\n"; # prints 5
print "Here's a hash ref: $href->{hello}\n"; # prints "world"
}
my #a = (5, 6, 7);
my %h = (hello=>"world", goodbye=>"girl");
f(\#a, \%h);

You can't pass a function to another function directly. Instead, you pass a reference to a function. To call the function you dereference it (as a CODE ref) using ->();
sub a { print #_ }
sub b {
my $f = shift; # assuming that $f is a function reference...
$f->(#_); # call it with the remaining arguments
}
b(\&a, "hello, world!"); # prints "hello, world!"
Perl doesn't have pass-by-name semantics but you can emulate them using a hash. The method for calling the function is the same. You dereference it.
sub a { print #_ }
sub b {
my %arg = #_;
$arg{function}->(#{$arg{arguments}});
}
b(function => \&a, arguments => ["hello, world!"]);
ObPerl6: Perl 6 will have pass-by-name semantics.

You can access subroutines references as \&my_method in Perl, and call those references with $myref->();. Try this:
perl -e'sub a { print "foo in a"; }; sub b { shift->(); }; b(\&a);'
Good luck!

Following up to Eli Courtwright's example: If you only use the first function once, you could also call b with an anonymous function, like this:
b( sub { print "Hello World\n"; } );

Related

Reusable, abstracted way to bind multiple lexicals all in one go

I have code that repeats this pattern:
sub method1 {
my ($foo, $bar) = _get_things(); # this line...
}
sub method2 {
my ($foo, $bar) = _get_things(); # ...is repeated here
}
The repeated line is just one line, so in a sense repeating it is no big deal. But, that has the drawback that if the list ($foo, $bar) ever changes, all these lines need to change. In C, one might use the preprocessor to solve this problem. Is there a good idiom for doing it in Perl? Something like the following psuedo-perl:
MACRO_DEFINITION my ($foo, $bar) = _get_things();
sub method1 {
MACRO_CALL
print "hi $foo";
}
sub method2 {
MACRO_CALL
print "hi $foo and $bar";
}
note: the reason _get_things() returns a list that I am binding to local lexical scalars is that I want to use them in string interpolation, as the latter example shows.
When a sub has more than a very few parameters, or what the parameters are is possibly going to change, you should pass a hash or hashref to emulate named parameters.
All the more so here, where you are returning more than one result and what the results are is likely to change, you should return a hashref from the sub. And just use that hashref in the caller (yes, even in string interpolation.)
use strict;
use warnings;
sub method2 {
my $thing = _get_things();
print "hi $thing->{'foo'} and $thing->{'bar'}\n";
}
sub _get_things {
return {
'foo' => 42,
'bar' => 'quux',
};
}
method2();

Perl. Access caller arguments (like shift, pop, etc)

In perl there is the shift function that can act on the #_(arguments of a function in scope of which it was called) if no arguments supplied.
Can I write a custom function in perl with the same behavior(some kind of my_shift)?
I tried this:
use Data::Dumper;
sub get_caller_args (;$) {
my $n = shift;
$n = defined $n? $n:1;
my $ret;
package DB {
my($t,$t1) = caller($n);
};
$ret = \#DB::args;
return $ret;
}
sub test ($#) {
my $self = shift;
print "Self: $self.\n";
print Dumper(get_caller_args()), "\n";
}
It kind of works, but
test(1,2,3)
outputs:
Self: 1.
$VAR1 = [
1,
2,
3
];
So it doesn't see changes made by shift (though it can see changes made by pop).
But I want it to act like this:
sub test {
my $self = shift;
print my_function;
}
Here the my_function called without arguments must act on the #_, in this case on the rest of the arguments, without the first as it was shifted(actually I need only to read arguments, not to do changes).
Ok, I found an answer:
use feature 'say';
sub my_shift {
say "Arguments before shift: ", #_;
shift;
say "Arguments after shift: ", #_;
}
sub test {
say "Arguments before my_shift: ", #_;
&my_shift;
say "Arguments after my_shift: ", #_;
}
The 'tricky' thing here is to call the my_shift with an ampersand(&) before the function name -- then the function gets arguments of the calling function as it's input.
However I'll not accept this self-answer, because I'm still interested if it possible to do this without that ampersand magic and what if i need to pass other arguments and access the calling function arguments at the same time, etc.

Passing argument to a Perl class subroutin

My code is pretty simple. I have a subroutin getModemHost under a package named smconfig.
sub getModemHost {
print 'Modem-'.$_[0].'.Host';
}
when Im calling this subroutin with an argument, I see strange values rather than what I passed. The below line prints Modem-smconfig=HASH(0x9433968).Host. I am expecting Modem-1.Host
$smconfig->getModemHost(1)
The first argument to a method is the invocant, i.e. the object. Use $_[1] for the real first argument. Or, more readable:
sub getModemHost {
my ($self, $modem_number) = #_;
print "Modem-$modem_number.Host";
}
See perlobj for details.
Or something very common:
sub myObjectMethod {
my $self = shift;
...
# do here what you like to do with $_[0]
# for we have removed the first parameter
...
};

Passing variables through functions

When I pass a variable through a couple of subs, it always turns up empty. Why is this ?
sub Main {
my $myVariable = "Test string";
firstSub($myVariable);
}
sub firstSub {
my($myVariable) = #_;
my #array = `some command`;
secondSub(#array, $myVariable);
}
sub secondSub {
my(#array, $myVariable) = #_;
print $myVariable;
}
echo will be undef.
echo is not a valid Perl function. You're confusing shells with Perl here. Try "print" or "say" (the latter with Perl 5.10 and newer).
Also you cannot assign an array & a scalar variable to another array & scalar variable. Meaning this won't work because all of the elements of the right-hand side will be assigned to the array on left-hand side, and nothing will be assigned to the scalar: my (#array, $myVariable) = #_; Either swap the order of the elements my ($myVariable, #array) = #_; (also when calling the function) or use array references instead of full arrays.
Your code doesn't do anything because you have defined three subroutines, but you have never called them.
Just add Main(); to actually run your main sub.
Also, you need print instead of echo.
Also, the passing of variables is incorrect, as Moritz Bunkus explained.
When you call secondsub() the #array and the $myVariable is being sent as a list(a single element) and is been assigned to #array in the secondsub function. You can see both the #array and $myVariable values when you print #array in secondsub.
You have to pass the array as a reference and receive it as a scalar value in secondsub. The below code will work.
&Main();
sub Main {
my $myVariable = "Test string";
firstSub($myVariable);
}
sub firstSub {
my($myVariable) = #_;
my #array = `some command`;
secondSub(\#array,$myVariable);
}
sub secondSub {
my($ref,$myVariable) = #_;
print $myVariable;
}
Passing varibles:
my $txt = "this text for sample";
Function_Passing_varible($txt);
sub Function_Passing_varible{
my $text = shift;
print $text;
}
I think you like this answer......

How can I code in a functional style in Perl?

How do you either:
have a sub return a sub
or
execute text as code
in Perl?
Also, how do I have an anonymous function store state?
A sub returns a sub as a coderef:
# example 1: return a sub that is defined inline.
sub foo
{
return sub {
my $this = shift;
my #other_params = #_;
do_stuff();
return $some_value;
};
}
# example 2: return a sub that is defined elsewhere.
sub bar
{
return \&foo;
}
Arbitrary text can be executed with the eval function: see the documentation at perldoc -f eval:
eval q{print "hello world!\n"};
Note that this is very dangerous if you are evaluating anything extracted from user input, and is generally a poor practice anyway as you can generally define your code in a coderef as in the earlier examples above.
You can store state with a state variable (new in perl5.10), or with a variable scoped higher than the sub itself, as a closure:
use feature 'state';
sub baz
{
state $x;
return ++$x;
}
# create a new scope so that $y is not visible to other functions in this package
{
my $y;
sub quux
{
return ++$y;
}
}
Return a subroutine reference.
Here's a simple example that creates sub refs closed over a value:
my $add_5_to = add_x_to(5);
print $add_5_to->(7), "\n";
sub add_x_to {
my $x = shift;
return sub { my $value = shift; return $x + $value; };
}
You can also work with named subs like this:
sub op {
my $name = shift;
return $op eq 'add' ? \&add : sub {};
}
sub add {
my $l = shift;
my $r = shift;
return $l + $r;
}
You can use eval with an arbitrary string, but don't do it. The code is hard to read and it restarts compilation, which slows everything down. There are a small number of cases where string eval is the best tool for the job. Any time string eval seems like a good idea, you are almost certainly better off with another approach.
Almost anything you would like to do with string eval can be achieved with closures.
Returning subs is easy by using the sub keyword. The returned sub closes over the lexical variables it uses:
#!/usr/bin/perl
use strict; use warnings;
sub mk_count_from_to {
my ($from, $to) = #_;
return sub {
return if $from > $to;
return $from ++;
};
}
my $c = mk_count_from_to(-5, 5);
while ( defined( my $n = $c->() ) ) {
print "$n\n";
}
5.10 introduced state variables.
Executing text as Perl is accomplished using eval EXPR:
the return value of EXPR is parsed and executed as if it were a little Perl program. The value of the expression (which is itself determined within scalar context) is first parsed, and if there weren't any errors, executed in the lexical context of the current Perl program, so that any variable settings or subroutine and format definitions remain afterwards. Note that the value is parsed every time the eval executes
Executing arbitrary strings will open up huge gaping security holes.
You can create anonymous subroutines and access them via a reference; this reference can of course be assigned to a scalar:
my $subref = sub { ... code ... }
or returned from another subroutine
return sub { ... code ... }
If you need to store states, you can create closures with lexical variables defined in an outer scope like:
sub create_func {
my $state;
return sub { ... code that can refer to $state ... }
}
You can run code with eval