Perl Anonymous Subroutine/Function error - perl

I have the following piece of code: (extremely simplified for the purposes of this question, but perfectly illustrates the problem I am having)
#!/usr/bin/perl
use strict;
use warnings;
&outer;
my $connected_sub;
sub outer {
print "HELLO\n";
&$connected_sub;
$connected_sub = sub {
print "GOODBYE\n";
}
}
When run the program gives this output and error:
HELLO
Use of uninitialized value in subroutine entry at subTesting line 13.
Can't use string ("") as a subroutine ref while "strict refs" in use at subTesting.pl line 13.
Am I totally overlooking something here? I cannot understand or work out what the problem with this is.

To clarify:
Subroutine definitions happen in the compilation stage. Thus code like this will work:
foo();
sub foo { print "No need to declare me before calling!"; }
But an assignment doesn't actually happen until that line of code is called. That is why this won't work:
my $foo;
&$foo();
$foo = sub { print "Foo hasn't been set to me when you try to call me." }

I assume that what you are trying to do here is assign an anonymous sub to the variable $connected_sub. This is not a good way to do it.
What you are doing is taking an empty variable, trying to use it as a code reference, assigning a code reference to it, then exiting the sub and then declaring the variable with my. Not the best order of doing things.
What you probably want to do is return a value which can be assigned to the variable, like so:
my $connected = outer();
$connected->();
sub outer {
print "HELLO\n";
my $sub = sub { print "GOODBYE\n"; }
return $sub;
}
Using a lexical variable inside a subroutine is somewhat confusing, I think. Besides the general drawbacks of using global variables, the subroutine is also compiled before the code is executed and the variable declared.
Also, when calling a subroutine, the standard way of doing so is
name(#args);
Where #args is your argument list. Using & is old style perl, and using it has a special meaning (override prototypes). When using an anonymous sub in a variable, use the ->() notation.

The $connected_sub is not initializated. Try to assign to an anonymous sub:
my $connected_sub = sub {
print "The code you need to run\n";
}
At the definition, and drop the code after the &$connected_sub call
This is the complete example modified:
#!/usr/bin/perl
use strict;
use warnings;
my $connected_sub = sub {
print "GOODBYE\n";
};
&outer;
sub outer
{
print "HELLO\n";
&$connected_sub;
}

Looks like you're using $connected_stub before it is initialized. Try to move the initialization up, like:
$connected_sub = sub {
print "GOODBYE\n";
}
&$connected_sub;

Related

How to use `our` class variables with `UNITCHECK` correctly with `use strict`?

As Perl constants are somewhat strange to use, I decided to implement my "class variables" as our variables, just like:
our $foo = '...';
However when I added a UNITCHECK block using the class variables, I realized that the variables were not set yet, so I changed the code to:
BEGIN {
our $foo = '...';
}
UNITCHECK {
if ($foo eq 'bla') {
#...
}
}
Then I realized that I had mistyped some variable names in UNITCHECK, so I decided to add use warnings and use strict.
Unfortunately I'm getting new errors like
Variable "$foo" is not imported at .. line ..
When I initialize the variable outside BEGIN, then the error is away, but then I have the original problem back.
So I wonder:
Is our $var = 'value'; the remommended and correct use, or should it be split in our $var; outside the BEGIN and $var = 'value; inside BEGIN?
As my list of variables is rather long, I'm trying to avoid list them twice (introducing the possibility of misspelling some again).
What is the recommended correct way to do it?
our is lexically scoped so in your code the variable only exists in the BEGIN block. You will need to separate out the declaration from the assignment like this:
our $foo;
BEGIN {
$foo = '...';
}
UNITCHECK {
if ($foo eq 'bla') {
#...
}
}

How to enable dots (.) in subroutine names?

I am working on creating a module with dynamic accessors, using autoloading. The called methods will have one or multiple dots in their names. Usage example:
use MyModule;
my $var=MyModule->a.method.get;
#MyModule::a.method.get() is now defined
It appears that the dots are illegal characters in subroutine names:
#!/usr/bin/perl
use warnings;
use strict;
sub mr.s
{
print "OK\n";
}
mr.s();
gives out
Illegal declaration of subroutine main::mr at main.pl line 5
So, how do I enable dots in subroutine names?
I understand, that at least some of the respondents might feel like discouraging usage of autoloading, as well as trying to change what is a legal subroutine name, instead providing examples of better practices. I have nothing against these kinds of answers and don't consider them any less valuable. Still, please try to provide an answer to my original question as well.
EDIT:
To clarify, the end goal is a module, where, when an undefined subroutine is called, it is dynamically defined, based on its name. To implement this I mean to use AUTOLOAD, in a way similar to how it is used in this tutorial.
You are right, that dot's are illegal in subroutine names. This has nothing to do with autoloading, they are just illegal. A dot is used for string concatenation, so your example of
MyModule->a.method.get
would actually be interpreted as
MyModule->a() . method() . get()
You can't do that, not and call them like ordinary methods [*].
Your choices are to abandon the . and use _ or something instead, or to not create accessor subs but instead have a generic get() function that takes an attribute name as a parameter.
( * Footnote: you can create such methods and call them indirectly, like so:
package Foo;
use strict;
use warnings;
BEGIN {
no strict 'refs';
*{'foo.bar'} = sub {
use strict;
return 'foo.bar value';
}
}
package main;
use strict;
use warnings;
my $method = 'foo.bar';
my $value = Foo::->$method;
but that's going to cause way more headache than you want.)
Why are you trying to use Java (or whatever) syntax? In Perl, it's written MyModule->a->get. Use that.
package MyModule;
use strict;
use warnings;
sub AUTOLOAD {
my $self = shift;
my $name = our $AUTOLOAD =~ s/^.*:://r;
my $path = ref($self) ? $self->{path}.".".$name : $name;
if (is_path_method($path)) {
return call_method($path);
} else {
return MyModule->___new(path => $path);
}
}
sub ___new {
my $class = shift;
return bless({ #_ }, $class);
}
sub DESTROY { }
Note that this will fail if try to access a proxied AUTOLOAD, can, DESTROY, DOES, import, isa, ___new or VERSION.
If you can have methods and attributes with the same name, use MyModule->a->get->(), which you can do by overloading &{}.
Per http://perldoc.perl.org/perldata.html#Identifier-parsing, I don't see that 'mr.s' validates as an identifier under either utf8 or non-utf8 source parsing. Thus, it is not a valid subroutine name.

Passing a block to a Moose method

Is it somehow possible to pass blocks to Moose methods? In standard Perl, I can define a function with prototypes like this
sub fn (&) {
my $code =\&{shift #_};
$code->();
}
and then pass a block to the function without explicit sub references, i.e. fn { say "Hi there, world" }.
I think this is only possible if the subroutine is the first parameter, and as this is always $self with a Moose method, it doesn't seem possible there, forcing me to do it the slightly more explicit way:
sub wrapper {
my ($self, $code) = #_;
$code->()
}
Wrapper->wrapper(sub { say "Hi there, world" });
Now this would be a pretty convenient way to wrap some blocks, i.e. to provide some additional text or conditionally execute code or wrap an eval around some code where the error handling stays the same (e.g. eval some code and log errors, record user etc.).
If I'm not missing something, is there some semi-convenient workaround or alternative method to achieve something like this without too much line noise?
Have a look at the PerlX::MethodCallWithBlock CPAN module which contorts the Perl syntax (via the Devel::Declare module) to allow you to put a block after a method call.
For e.g.:
use 5.016;
use warnings;
use PerlX::MethodCallWithBlock;
{
package Foo;
use Moose;
sub bar {
my ($self, $code) = #_;
$code->();
}
}
Foo->bar { say "Hi there world" };
This module was released as a proof of concept. So far I've had no issues with it but YMMV.

Nested subroutines and Scoping in Perl

I'm writing Perl for quite some time now and always discovering new things, and I just ran into something interesting that I don't have the explanation to it, nor found it over the web.
sub a {
sub b {
print "In B\n";
}
}
b();
how come I can call b() from outside its scope and it works?
I know its a bad practice to do it, and I dont do it, I use closured and such for these cases, but just saw that.
Subroutines are stored in a global namespace at compile time. In your example b(); is short hand for main::b();. To limit visibility of a function to a scope you need to assign an anonymous subroutines to a variable.
Both named and anonymous subroutines can form closures, but since named subroutines are only compiled once if you nest them they don't behave as many people expect.
use warnings;
sub one {
my $var = shift;
sub two {
print "var: $var\n";
}
}
one("test");
two();
one("fail");
two();
__END__
output:
Variable "$var" will not stay shared at -e line 5.
var: test
var: test
Nesting named subroutines is allowed in Perl but it's almost certainly a sign that the code is doing someting incorrectly.
The "official" way to create nested subroutines in perl is to use the local keyword. For example:
sub a {
local *b = sub {
return 123;
};
return b(); # Works as expected
}
b(); # Error: "Undefined subroutine &main::b called at ..."
The perldoc page perlref has this example:
sub outer {
my $x = $_[0] + 35;
local *inner = sub { return $x * 19 };
return $x + inner();
}
"This has the interesting effect of creating a function local to another function, something not normally supported in Perl."
The following prints 123.
sub a {
$b = 123;
}
a();
print $b, "\n";
So why are you surprised that the following does too?
sub a {
sub b { return 123; }
}
a();
print b(), "\n";
Nowhere is any request for $b or &b to be lexical. In fact, you can't ask for &b to be lexical (yet).
sub b { ... }
is basically
BEGIN { *b = sub { ... }; }
where *b is the symbol table entry for $b, #b, ..., and of course &b. That means subs belong to packages, and thus can be called from anywhere within the package, or anywhere at all if their fully qualified name is used (MyPackage::b()).
Subroutines are defined during compile time, and are not affected by scope. In other words, they cannot truly be nested. At least not as far as their own scope is concerned. After being defined, they are effectively removed from the source code.

Why does this Perl produce "Not a CODE reference?"

I need to remove a method from the Perl symbol table at runtime. I attempted to do this using undef &Square::area, which does delete the function but leaves some traces behind. Specifically, when $square->area() is called, Perl complains that it is "Not a CODE reference" instead of "Undefined subroutine &Square::area called" which is what I expect.
You might ask, "Why does it matter? You deleted the function, why would you call it?" The answer is that I'm not calling it, Perl is. Square inherits from Rectangle, and I want the inheritance chain to pass $square->area through to &Rectangle::area, but instead of skipping Square where the method doesn't exist and then falling through to Rectangle's area(), the method call dies with "Not a CODE reference."
Oddly, this appears to only happen when &Square::area was defined by typeglob assignment (e.g. *area = sub {...}). If the function is defined using the standard sub area {} approach, the code works as expected.
Also interesting, undefining the whole glob works as expected. Just not undefining the subroutine itself.
Here's a short example that illustrates the symptom, and contrasts with correct behavior:
#!/usr/bin/env perl
use strict;
use warnings;
# This generates "Not a CODE reference". Why?
sub howdy; *howdy = sub { "Howdy!\n" };
undef &howdy;
eval { howdy };
print $#;
# Undefined subroutine &main::hi called (as expected)
sub hi { "Hi!\n" }
undef &hi;
eval { hi };
print $#;
# Undefined subroutine &main::hello called (as expected)
sub hello; *hello = sub { "Hello!\n" };
undef *hello;
eval { hello };
print $#;
Update: I have since solved this problem using Package::Stash (thanks #Ether), but I'm still confused by why it's happening in the first place. perldoc perlmod says:
package main;
sub Some_package::foo { ... } # &foo defined in Some_package
This is just a shorthand for a typeglob assignment at compile time:
BEGIN { *Some_package::foo = sub { ... } }
But it appears that it isn't just shorthand, because the two cause different behavior after undefining the function. I'd appreciate if someone could tell me whether this is a case of (1) incorrect docs, (2) bug in perl, or (3) PEBCAK.
Manipulating symbol table references yourself is bound to get you into trouble, as there are lots of little fiddly things that are hard to get right. Fortunately there is a module that does all the heavy lifting for you, Package::Stash -- so just call its methods add_package_symbol and remove_package_symbol as needed.
Another good method installer that you may want to check out is Sub::Install -- especially nice if you want to generate lots of similar functions.
As to why your approach is not correct, let's take a look at the symbol table after deleting the code reference:
sub foo { "foo!\n"}
sub howdy; *howdy = sub { "Howdy!\n" };
undef &howdy;
eval { howdy };
print $#;
use Data::Dumper;
no strict 'refs';
print Dumper(\%{"main::"});
prints (abridged):
$VAR1 = {
'howdy' => *::howdy,
'foo' => *::foo,
};
As you can see, the 'howdy' slot is still present - undefining &howdy doesn't actually do anything enough. You need to explicitly remove the glob slot, *howdy.
The reason it happens is precisely because you assigned a typeglob.
When you delete the CODE symbol, the rest of typeglob is still lingering, so when you try to execute howdy it will point to the non-CODE piece of typeglob.