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

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();

Related

How to call subroutine in perl using variable name [duplicate]

This question already has answers here:
How can I elegantly call a Perl subroutine whose name is held in a variable?
(12 answers)
Closed 6 years ago.
Let say I have one array that contains all subroutine name and I want to call all one by one.
foreach $sub (#arr){
print "Calling $sub\n";
#---How to call $sub?----
&$sub; ## will not work
}
Your code is correct in general, but you need to turn off strict 'refs' to make Perl allow you to use variable content as code refs.
use strict;
use warnings;
sub foo { print "foo" }
sub bar { print "bar" }
my #arr = qw/foo bar/;
foreach my $sub (#arr) {
no strict 'refs';
print "Calling $sub\n";
&$sub();
}
The output here is:
Calling foo
fooCalling bar
bar
I've also added parenthesis () after the call. That way we pass no arguments to %$sub. If we do not those, the #_ argument list of the current subroutine will be used.
However, you should probably not do this. Especially if #arr contains user input, this is a big problem. Your user can inject code. Consider this:
my #arr = qw/CORE::die/;
Now we get the following output:
Calling CORE::die
Died at /home/code/scratch.pl line 1492.
Oops. You don't want to do this. The die example is not very bad, but like this you could easily call code in some different package that wasn't intended.
It's probably better to make a dispatch table. There is a whole chapter about those in Higher Order Perl by Mark Jason Dominus, which you can download for free on his website.
It basically means you put all the subs into a hash as code references, and then call those in your loop. That way you can control which ones are allowed.
use strict;
use warnings;
sub baz { print "baz" }
my %dispatch = (
foo => sub { print "foo" },
bar => sub { print "bar" },
baz => \&baz,
);
my #arr = qw/foo bar baz wrong_entry/;
foreach my $sub ( #arr ) {
die "$sub is not allowed"
unless exists $dispatch{$sub};
$dispatch{$sub}->();
}
This outputs:
foobarbaz
wrong_entry is not allowed at /home/code/scratch.pl line 1494.
You want to do that using code references.
foreach my $sub (#arr)
{
$sub->();
}
where #arr contains scalars such as
my $rc = sub { print "Anonymous subroutine\n" };
or
sub func { print "Named sub\n" }
my $rc = \&func;
You can manipulate these scalars as you would any other, to form your array. However, it is more common and useful to use them as values in a hash, creating a dispatch table.
See perlref and perlsub, and (for example) this post and links in it for comments and details.

Why can't I initialize the member variable inside the new?

I am trying to undestand OO in Perl. I made the following trivial class:
#/usr/bin/perl
package Tools::Util;
use strict;
use warnings;
my $var;
sub new {
my ($class, $arg) = #_;
my $small_class = {
var => $arg,
};
return bless $small_class;
}
sub print_object {
print "var = $var\n"; #this is line 20
}
1;
And this is a test script:
#!/usr/bin/perl
use strict;
use warnings;
use Tools::Util;
my $test_object = new Tools::Util("Some sentence");
$test_object->print_object();
use Data::Dumper;
print Dumper($test_object);
The result I get is:
Use of uninitialized value $var in concatenation (.) or string at Tools/Util.pm line 20.
var =
$VAR1 = bless( {
'var' => 'Some sentence'
}, 'Tools::Util' );
I can not understand this. I thought that objects in Perl are hashes and so I could access/initialize the member variables using the same names without a $. Why in this case the $var is not initialized but the hash that I Dump contains the value?
How should I use/initialize/handle member variables and what am I misunderstanding here?
$var is lexical class variable, and undefined in your example.
You probably want:
sub print_object {
my $self = shift;
print "var = $self->{var}\n";
}
Perl doesn't handle object methods in quite the same way that you're used to.
Are you familiar with the implicit this argument that many object-oriented languages use? If not, now would be a great time to read up on it.
Here's a five-second introduction that glosses over the details:
//pretend C++
//this function signature
MyClass::MyFunction(int x);
//is actually more like the following
MyClass::MyFunction(MyClass this, int x);
When you access instance members of the class, my_var is equivalent to this.my_var.
In Perl, you get to do this manually! The variable $var is not equivalent to $self->{var}.
Your blessed object is actually a hash reference, and can be accessed as such. When you call $test_object->print_object(), the sub gets the value of $test_object as its first argument. Most Perl programmers handle this like so:
sub my_method {
my $self = shift; #shift first argument off of #_
print $self->{field};
}
With that in mind, you should probably rewrite your print_object sub to match mpapec's answer.
Further reading: perlsub, perlobj

Is there a convenience for safe dereferencing in Perl?

So perl5porters is discussing to add a safe dereferencing operator, to allow stuff like
$ceo_car_color = $company->ceo->car->color
if defined $company
and defined $company->ceo
and defined $company->ceo->car;
to be shortened to e.g.
$ceo_car_color = $company->>ceo->>car->>color;
where $foo->>bar means defined $foo ? $foo->bar : undef.
The question: Is there some module or unobstrusive hack that gets me this operator, or similar behavior with a visually pleasing syntax?
For your enjoyment, I'll list ideas that I was able to come up with.
A multiple derefencing method (looks ugly).
sub multicall {
my $instance = shift // return undef;
for my $method (#_) {
$instance = $instance->$method() // return undef;
}
return $instance;
}
$ceo_car_color = multicall($company, qw(ceo car color));
A wrapper that turns undef into a proxy object (looks even uglier) which returns undef from all function calls.
{ package Safe; sub AUTOLOAD { return undef } }
sub safe { (shift) // bless {}, 'Safe' }
$ceo_car_color = safe(safe(safe($company)->ceo)->car)->color;
Since I have access to the implementations of ceo(), car() and color(), I thought about returning the safe proxy directly from these methods, but then existing code might break:
my $ceo = $company->ceo;
my $car = $ceo->car if defined $ceo; # defined() breaks
Unfortunately, I don't see anything in perldoc overload about overloading the meaning of defined and // in my safe proxy.
Maybe this is not the most useful solution, but it's one more WTDI (a variant of nr. 1) and it's a non-trivial use-case for List::Util's reduce, which are very rare. ;)
Code
#!/usr/bin/env perl
use strict;
use warnings;
use feature 'say';
use List::Util 'reduce';
my $answer = 42;
sub new { bless \$answer }
sub foo { return shift } # just chaining
sub bar { return undef } # break the chain
sub baz { return ${shift()} } # return the answer
sub multicall { reduce { our ($a, $b); $a and $a = $a->$b } #_ }
my $obj = main->new();
say $obj->multicall(qw(foo foo baz)) // 'undef!';
say $obj->multicall(qw(foo bar baz)) // 'undef!';
Output
42
undef!
Note:
Of course it should be
return unless defined $a;
$a = $a->$b;
instead of the shorter $a and $a = $a->$b from above to work correctly with defined but false values, but my point here is to use reduce.
You can use eval:
$ceo_car_color = eval { $company->ceo->car->color };
But it will of course catch any errors, not just calling a method on an undef.

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

Is there a better way to pass by reference in Perl?

I am doing pass-by-reference like this:
use strict;
use warnings;
sub repl {
local *line = \$_[0]; our $line;
$line = "new value";
}
sub doRepl {
my ($replFunc) = #_;
my $foo = "old value";
$replFunc->($foo);
print $foo; # prints "new value";
}
doRepl(\&repl);
Is there a cleaner way of doing it?
Prototypes don't work because I'm using a function reference (trust me that there's a good reason for using a function reference).
I also don't want to use $_[0] everywhere in repl because it's ugly.
Have you looked at Data::Alias? It lets you create lexically-scoped aliases with a clean syntax.
You can use it to create pass-by-reference semantics like this:
use strict;
use warnings;
use Data::Alias;
sub foo {
alias my ($arg) = #_;
$arg++;
}
my $count = 0;
foo($count);
print "$count\n";
The output is 1, indicating that the call to foo modified its argument.
There are a couple of ways to do this. Explicitly pass a scalar ref to $foo, or take advantage of Perl's built-in pass by reference semantics.
Explicit reference:
my $foo = "old value";
doRepl( \&repl, \$foo );
print $foo; # prints "new value";
sub repl {
my $line = shift;
$$line = "new value";
}
sub doRepl {
my ($replFunc, $foo) = #_;
$replFunc->($foo);
}
Pass by reference:
my $foo = "old value";
doRepl( \&repl, $foo );
print $foo; # prints "new value";
sub repl {
$_[0] = "new value";
}
sub doRepl {
my $replFunc = shift;
$replFunc->(#_);
}
Even fancier pass by reference:
my $foo = "old value";
doRepl( \&repl, $foo );
print $foo; # prints "new value";
sub repl {
$_[0] = "new value";
}
sub doRepl {
my $replFunc = shift;
&$replFunc;
}
The first one use normal perl hard references to do the job.
The first pass by ref method uses the fact that Perl passes arguments to all functions as references. The elements of #_ are actually aliases to the values in the argument list when the subroutine is called. By altering $_[0] in foo(), you actually alter the first argument to foo().
The second pass by ref method use the fact that a sub called with an & sigil and no parens gets the #_ array of its caller. Otherwise it is identical.
Update: I just noticed you desire to avoid $_[0]. You can do this in repl if you want:
sub repl {
for my $line( $_[0] ) {
$line = 'new value';
}
}
sub repl {
my $line = \$_[0]; # or: my $line = \shift
$$line = "new value";
}
I don't think there is anything wrong with using local to create the alias in this case.
Dynamic scope is of course a powerful feature, but so long as you are aware of the side effects (new value is visible in functions called from its scope, if a lexical of the same name is in scope, it can't be localized, ...) then it is a useful addition to the already overflowing Perl toolbox.
The main reason for the warnings in the Perl docs about local are to keep people from inadvertently using it instead of my and to ease the transition from perl4. But there are definitely times when local is useful, and this is one.
Using for to create your alias is also an option, but I find the explicit syntax with local clearer in its intent. It is also a bit faster if performance is a concern.