I got a package, lets call it Foo.pm for simplicity. In there, I got some Anonymous functions which I'd like to export.
Foo.pm looks like the following:
package Foo;
use Exporter qw(import);
our #EXPORT_OK = ();
our #EXPORT = qw(
subroutine1
subroutine2
$anon_function
);
subroutine1 {
# Do something here
}
subroutine2 {
# Do something else here
}
my $anon_function = sub {
my $parameter = shift;
# Do something with parameter
return 1 if $parameter == 1 or $parameter == 2;
return 0;
}
In my main script, call it bar.pl, im importing the module and (obviously) using its functions.
bar.pl:
use lib "/usr/share";
use Foo;
subroutine1("foobar");
subroutine2("foobar");
&$anon_function("foobar");
Using the normal subroutines outside of Foo.pm seems no problem, when I get to the &$anon_function() it produces the following error:
Use of uninitialized value in subroutine entry at ./bar.pl line 7
When trying to print the anonymous function with print Dumper \$anon_function, it also returns $VAR1 = \undef
TL;DR: How can I Export anonymous functions from a Package?
You cannot export a lexical variable. You can only export symbols, i.e. package global variables and named subroutines.
Changing to an our works:
use Exporter qw{ import };
our #EXPORT = qw( $anon );
our $anon = sub { ... };
Related
Given a package name $package and a function name from within that package $function, I can create a reference to that function:
my $ref = eval( "\\&${package}::${function}" );
As a complete example:
#!/usr/bin/perl -w
use strict;
package foo;
sub func()
{
print "foo::func\n";
}
package main;
my $package = "foo";
my $function = "func";
my $ref = eval( "\\&${package}::$function" );
$ref->();
I do not particularly like that eval() in there and wonder if the same result could be achieved without eval()?
All you need is this:
my $ref = \&{ "${package}::$name" };
or
my $ref = \&{ $package . "::" . $name };
Using an expression producing the name of a variable where a variable name is expected is called a symbolic reference. These are usually forbidden by use strict; (specifically use strict qw( refs );), but \& is exempt.
Using strings to refer to subroutines is seldom the right way. If you are doing it this way, you are most likely doing something wrong. You can use a code reference to store a reference to a function, in a scalar or hash. The hash allows you to correctly look up code references via string inputs.
use strict;
use warnings;
package foo;
sub func() {
print "inside foo::func (#_)\n";
}
package main;
# use a direct reference, in a scalar variable
my $ref = \&foo::func;
$ref->(1,2,3);
# ...or in a hash
my $pack = "foo";
my $func = "func";
my %table = ( foo => { func => \&foo::func } );
$table{$pack}{$func}->(qw(a b c));
Output:
inside foo::func (1 2 3)
inside foo::func (a b c)
I'm trying to save the content of a our global variable declared in the main script, to a my lexical variable in a module.
main.pl
use strict;
use warnings;
use module;
our $global = "Hello";
function();
module.pm
package module;
use strict;
use warnings;
use Exporter 'import';
our #EXPORT = qw( function );
# some needed initialization & definition before subs
my $var = $main::global;
sub function {
print $var,"\n";
}
1;
I'm facing : Use of uninitialized value $var error
Even when i try to do a print just under the assignment, it doesn't work !
Thanks.
finally i got what i want by creating a module which contain all the global variable i want. and use it everywhere when needed.
it look like this
package Globals;
use Exporter 'import';
our #EXPORT = qw( $VERSION $DEV_EMAIL $BASEDIR $CURRENT_PROJECT );
our $VERSION = "0.0.1";
our $DEV_EMAIL = "FOO#BAR.COM";
our $BASEDIR = "./Projects/";
our $CURRENT_PROJECT = '';
1;
OtherPackage.pm
package OtherPackage
use Globals;
my $var = $VERSION
# do something with $var
print $var;
1;
I have multiple classes defined in my main program. One is a parent class. The other are children classes:
# Main Program
...
package Foo; #Parent class
....
sub glob2regex {
my $glob = shift;
...here be dragons...
return $regex;
};
....
package Foo::Bar; #Child Class
base qw(Foo);
sub some_method {
my $self = shift;
my $regex = shift;
my $type = shift;
if ( $type eq "glob" ) {
$regex = glob2regex($regex); #ERROR: glob2regex is not defined.
}
...
}
I have a function in my parent class called glob2regex. It isn't really a method because it doesn't do anything with the object. Instead, it's a helper function that my child classes can use.
However, calling it in my child class as shown above won't work because it's not defined in my child class. I could prepend the full parent class name on it (i.e. call it as Foo::glob2regex instead of just glob2regex), or I could modify it into an object, and call it as $self->glob2regex. There maybe a even better way of handling this situation that I'm overlooking.
What is the best way to make a function like this that's defined in the parent class available in the child classes?
--
Test Program
#! /usr/bin/env perl
#
use strict;
use warnings;
use feature qw(say);
use utf8;
########################################################################
# MAIN PROGRAM
my $bar = Foo::Bar->new;
$bar->just_foo_it;
#
########################################################################
########################################################################
#
package Foo;
sub lets_foo_it {
say "I've done foo!";
}
#
########################################################################
########################################################################
#
package Foo::Bar;
use base qw(Foo);
*Foo::Bar::lets_foo_it = *Foo::lets_foo_it;
sub new {
my $class = shift;
my $self = {};
bless $self, $class;
return $self;
}
sub just_foo_it {
my $self = shift;
lets_foo_it();
}
#
########################################################################
Exporting is usually done using Exporter.
BEGIN {
package Foo;
use Exporter qw( import );
our #EXPORT_OK = qw( glob2regex );
sub glob2regex { ... }
...
$INC{'Foo.pm'} = 1;
}
BEGIN {
package Foo::Bar;
use Foo qw( glob2regex );
our #ISA = 'Foo';
... glob2regex(...) ...
$INC{'Foo/Bar.pm'} = 1;
}
Note that it's very unusual for a class module to export subroutines. You should consider it a red flag indicating a likely design flaw.
Seems like a bit of your problem is: "How do I use within a file?". I have a pragma I use in early development for this type of thing, but it breaks down to:
package Foo;
BEGIN { $INC{ __PACKAGE__ . '.pm'} = __FILE__ . ':' . ( __LINE__ - 1 ); }
Once it's in the %INC table, you're usually fine just using it.
Remember that a use is a require combined with an import at compile time. Once you've defined the Foo import, you can create an import function to take care of that part of use.
sub import {
my $caller = caller;
return unless $caller->isa( __PACKAGE__ );
{ no strict 'refs';
*{"$caller\::glob2regex"} = *glob2regex{CODE};
}
}
As I wrote above, I use this type of thing in early development--basically, when I want a sort of "scratchpad" with object relationships. In maintainable code, my preference would be to call Foo::glob2regex(...), or as I have at times insert it into a util package and export it from there:
package Foo::Util;
use strict;
use warnings;
use parent 'Exporter';
our #EXPORT_OK = qw<glob2regex>;
sub glob2regex { ... }
after foo => sub{
...
}
I just stumble upon code like above, which is called after sub foo finishes,
how does that work?
It seems it's not built-in feature of Perl,right?
It's one of the Moose method modifiers.
Method modifiers can be used to add behavior to methods without modifying the definition of those methods.
Out of curiosity, I've tried to do it myself, and got code that works to some extent (no list context, no corner cases etc.).
Perl allows for horrible things.
% perl -wle 'use After; sub foo { $_[0] * 2};
after foo => sub { print $_[0] }; foo(5); foo(6);'
10
12
Here's After.pm. Please don't ever use it.
use warnings;
use strict;
package After;
# make after() available after 'use After;'
use Exporter;
BEGIN {
our #ISA = qw(Exporter);
our #EXPORT = qw(after);
};
# prototype: bareword + sub
sub after (*&) {
my ($name, $code) = #_;
my $caller = caller; # get calling package
# fetch old sub named "name"
# note $oldcode = *{...} is not ehough
my $oldcode;
{
no strict 'refs';
$oldcode = \&{$caller."::".$name};
};
# defined new sub
my $newcode = sub {
my $ret = $oldcode->(#_); # call old sub as is
$code->($ret); # call the after sub
return $ret; # ignore aftersub's ret val
};
# plant new sub into the calling package
# avoid redefinition warnings
{
no strict 'refs';
no warnings 'redefine';
*{$caller."::".$name} = $newcode;
};
};
1;
It is not a builtin feature as others have already stated. For programs that do not use Moose, you can use Class::Method::Modifiers to get these modifiers.
If after is a predeclared subroutine, it would mean that you call that sub, with foo and an anonymous sub as arguments. It does seem a bit odd, though.
=> is equivalent to a comma, so assuming after is a sub, it would mean this:
after('foo', sub { ... });
I have a base class like this:
package MyClass;
use vars qw/$ME list of vars/;
use Exporter;
#ISA = qw/Exporter/;
#EXPORT_OK = qw/ many variables & functions/;
%EXPORT_TAGS = (all => \#EXPORT_OK );
sub my_method {
}
sub other_methods etc {
}
--- more code---
I want to subclass MyClass, but only for one method.
package MySubclass;
use MyClass;
use vars qw/#ISA/;
#ISA = 'MyClass';
sub my_method {
--- new method
}
And I want to call this MySubclass like I would the original MyClass, and still have access to all of the variables and functions from Exporter. However I am having problems getting the Exporter variables from the original class, MyClass, to export correctly. Do I need to run Exporter again inside the subclass? That seems redundant and unclear.
Example file:
#!/usr/bin/perl
use MySubclass qw/$ME/;
-- rest of code
But I get compile errors when I try to import the $ME variable. Any suggestions?
You should access everything through methods. Forget about passing variables around.
You're getting a syntax error because you have a syntax error:
use MySubclass /$ME/; # syntax error - that's the match operator
You want a list there:
use MySubclass qw/$ME/;
However, don't do that. Provide access to these data through methods. Since you'll inherit the methods, you don't need (and shouldn't use) Exporter:
package MyClass;
BEGIN {
my $ME;
sub get_me { $ME }
sub set_me { $ME = shift }
}
Now your subclass is just:
package MySubclass;
use parent( MyClass );
sub my_method { ... }
There are various modules that can automatically handle the accessor details for you if you have many variables you need to share.
In general, OO Perl and Exporter are normally kept separate instead of mixing them together. This is one of the reasons why.
Like brian said, you'll have a much easier time getting this to work in the first place and with extending it further in the future if you take all the crap you're exporting, turn it into class properties/methods, and get rid of Exporter completely. The simple fact that the way you want to do it requires you to import and re-export everything should be a big, flashing clue that there's probably a better way to do it (i.e., a way that doesn't involve Exporter).
You're not actually inheriting MySubclass from MyClass at all -- MySubClass is a user of MyClass. What you're doing is overriding a bit of behaviour from MyClass, but you will only confuse yourself if you think of this as inheritance, because it isn't (for example: where is your constructor?) I couldn't figure out what you were trying to do until I ignored everything the code was doing and just read your description of what you want to have happen.
Okay, so you have a class which imports some symbols - some functions, and some variables:
package MyClass;
use strict;
use warnings;
use Exporter 'import'; # gives you Exporter's import() method directly
our #EXPORT_OK = qw/ many variables & functions/;
our %EXPORT_TAGS = (all => \#EXPORT_OK );
our ($ME, $list, $of, $vars);
sub my_func {
}
sub other_func {
}
1;
and then you come along and write a class which imports everything from MyClass, imports it all back out again, but swaps out one function for another one:
package MyBetterclass;
use strict;
use warnings;
use Exporter 'import'; # gives you Exporter's import() method directly
our #EXPORT_OK = qw/ many variables & functions /;
our %EXPORT_TAGS = (all => \#EXPORT_OK );
use MyClass ':all';
sub my_func {
# new definition
}
1;
That's it! Note that I enabled strict checking and warnings, and changed the names of the "methods" that are actually functions.
Additionally, I did not use use vars (the documentation says it's obsolete, so that's a big red flag if you still want to use it without understanding its mechanics).
# use setters and getters the Perl's way
#
# ---------------------------------------
# return a field's value
# ---------------------------------------
sub get {
my $self = shift;
my $name = shift;
return $self->{ $name };
} #eof sub get
#
# ---------------------------------------
# set a field's value
# ---------------------------------------
sub set {
my $self = shift;
my $name = shift;
my $value = shift;
$self->{ $name } = $value;
}
#eof sub set
#
# ---------------------------------------
# return the fields of this obj instance
# ---------------------------------------
sub dumpFields {
my $self = shift;
my $strFields = ();
foreach my $key ( keys %$self ) {
$strFields .= "$key = $self->{$key}\n";
}
return $strFields;
} #eof sub dumpFields