How do I rename an exported function in Perl? - perl

I have some Perl modules which exports various functions. (We haven't used #EXPORT in new modules for some years, but have retained it for compatibility with old scripts.)
I have renamed a number of functions and methods to change to a consistent naming policy, and thought that then adding a list of lines like
*directory_error = *directoryError;
at the end of the module would just alias the old name to the new.
This works, except when the old name is exported, and a calling script calls the function with an unqualified name: in this case, it reports that the subroutine is not found (in the calling module).
I guess that what is happening is that Exporter prepares the list in a BEGIN, when the alias has not been created; but I tried putting the typeglob assignment in a BEGIN block and that didn't help.
I've tried AUTOLOAD, but of course that does not make the name available in the calling context. Of course I could write a series of wrapper functions, but that is tedious. It's possible I could generate wrapper functions automatically, though I'm not sure how.
Any suggestions of a neat way of handling this?

Exporting
Manually calling #EXPORT =() stuff is getting a bit haggard.
package Bar;
use strict;
use warnings;
use Sub::Exporter -setup => {
exports => [qw[ foo ]],
groups => {
default => [qw[ foo ]],
}
};
sub foo(){
};
1;
Use:
use strict;
use warnings;
use Bar foo => { -as-> 'Foo' };
Sub::Exporter can do lots of awesome stuff, like group exports, group exclusion, builder methods ( Ie: how the subs it exports work are determined by passed parameters , and the subs are generated inside other subs, etc )
Sub::Exporter tutorial
Sub::Exporter
Renaming
For renaming things it might be better to have a secondary function which just stands as a legacy function that Carp()s when its called to recommend the code that points to it everywhere to be moved to the new method. This will increase consistency codewide.
Then when your tests stop spouting forth warnings, you can remove the legacy function.
sub old { # line 1
Carp::carp('Legacy function \'old\' called, please move to \'newmethod\' ');
goto &newmethod; # this passes #_ literally and hides itself from the stack trace.
} # line 4
sub newmethod { # line 6
Carp::cluck('In New Method');
return 5;
} # line 9
print old(), "\n"; # line 11
Legacy function 'old' called, please move to 'newmethod' at code.pl line 2
main::old() called at code.pl line 11
In New Method at code.pl line 7
main::newmethod() called at code.pl line 11
5
Note how the warnings in newmethod look exactly like they'd been called directly.

The following works for me. This seems to be what you're describing; you must have made a mistake somewhere.
Main script:
use strict;
use warnings;
use Bar;
baz();
Module:
package Bar;
use strict;
use warnings;
require Exporter;
our #ISA = qw(Exporter);
our #EXPORT = qw(baz);
sub Baz { print "Baz() here\n" }
*baz = *Baz;
1;

You must export both names if you want both names to be visible. Using Michael Carman's answer as a base, you need
our #EXPORT = qw(Baz baz);
or
our #EXPORT = qw(Baz);
our #EXPORT_OK = qw(baz);
if you want to be able to call either one in the program. Just because they point to the same coderef does not mean all names for that coderef will be exported when one is.

Related

Why is *main::my_func{CODE}* a coderef when function my_func() is exported but not defined?

I have project where I renamed a Perl module because it had a too generic name and wrote a small compatibility module. I even wrote a test for the compatibility module but it was false positive. Why does this feel so hard to test? How to actually test the existence of the exported function if I can't call it because of side effects?
In my compatibility module I inherited from the new module but didn't import its functions. That wasn't enough, to my surprise. Here I built a minimal example with only 1 package involved:
use strict;
use warnings;
use feature qw(say);
{
package MyPackage;
use parent 'Exporter';
our #EXPORT = qw(foo);
}
MyPackage->import();
say *main::foo{CODE};
say *MyPackage::foo{CODE};
say main->can('foo');
say MyPackage->can('foo');
foo();
(I replaced use MyPackage with MyPackage->import() to make this example work in 1 file.)
The output:
CODE(0x55fa5cf9e750)
CODE(0x55fa5cf9e750)
CODE(0x55fa5cf9e750)
CODE(0x55fa5cf9e750)
Undefined subroutine &MyPackage::foo called at inherit.pl line 16.
This all looks like the function exists but it fails when I try to call it.
This is Perl 5.34.
Update to answer zdim’s qestion: What is the actual issue?
I moved the actual code from OldModule.pm to NewModule.pm (not their real names, of course) and created a new OldModule.pm for compatibility with existing software using that. The actual code provided both package functions via import() as well as class and object methods. So I used use parent 'NewModule' to inherit all of them. I believed this would also inherit package functions. My Test with Test2’s can_ok incorrectly showed that it worked.
Thanks to a bug report from a coworker I learned that this was not enough and found I needed to import the package functions as well.
I can’t simply call the functions in question to test the compatibility package because this is part of a CGI app and the functions actually do database operation or print out stuff to STDOUT and would pollute my TAP output. (Yes, part of my mission is to get rid of CGI, of course.)
package OldPackage;
# ABSTRACT: transitional package for new name NewPackage
use strict;
use warnings;
use NewPackage; # this is the line I added to fix the issue
use Exporter qw(import);
our #EXPORT = #NewPackage::EXPORT; # this line only declared undefined functions
1;
Exporter, in effect, does something similar to this:
*main::foo = \&MyPackage::foo;
Just like with scalars, arrays and hashes, referencing a sub vivifies the symbol. Specifically, it creates an undefined sub as if you had done sub foo;.
$ perl -M5.010 -e'
\&foo; say *foo{CODE};
sub bar; say *bar{CODE};
'
CODE(0x55da28044470)
CODE(0x55da28073750)
exists(&f) checks if it exists, and defined(&f) checks if it's defined.
$ perl -M5.010 -e'
sub foo { }
sub bar;
for (qw( foo bar baz )) {
say exists( &$_ ) ? "$_ exists" : "$_ doesn\x27t exist";
say defined( &$_ ) ? "$_ is defined" : "$_ isn\x27t defined";
}
'
foo exists
foo is defined
bar exists
bar isn't defined
baz doesn't exist
baz isn't defined

Is the order of use of perl modules followed when evaluating subroutines?

I have a perl module that has a frequently used subroutine. For a specific set of scripts I need to override this subroutine so i created another module that has the new implementation. Does anyone know if the call order of the perl modules are always followed?
Ex.:
one.pm:
sub temp{ print “hi”; }
two.pm:
sub temp{ print “hello”; }
sample.pl:
use one; use two;
temp();
I have tested this and it prints “hello” as expected. But I wanted to make sure that this is always the case. Is the evaluation of imported modules in order all the time?
You should not write modules like that! Your just going to get into problems, including the one you're asking about. Any file loaded using use should have corresponding package. And they must end on a true value. (Your code doesn't compile because you failed to do so.)
Before I got on, let me mention that you should ALWAYS use use strict; use warnings;. Also note that lowercase module names are traditionally used for pragmas, modules that change how Perl itself behaves. It's a poor practice to use lowercase module names for other purposes.
Back to the point. At a minimum, you need the following:
One.pm:
package One;
use strict;
use warnings;
sub temp { ... }
1;
Two.pm:
package Two;
use strict;
use warnings;
sub temp { ... }
1;
The script would now look like this:
use strict;
use warnings;
use One qw( );
use Two qw( );
One::temp();
Two::temp();
And now you see that your problem is moot; there's no question about which sub is called.
But, what if you didn't want to prefix all the calls with One:: or Two::? We can do that!
One.pm:
package One;
use strict;
use warnings;
use Exporter qw( import );
our #EXPORT_OK = qw( temp );
sub temp { ... }
1;
Two.pm:
package Two;
use strict;
use warnings;
use Exporter qw( import );
our #EXPORT_OK = qw( temp );
sub temp { ... }
1;
The script would now look like this:
use strict;
use warnings;
use One qw( );
use Two qw( temp );
One::temp();
Two::temp();
temp(); # Calls Two::temp() because we imported temp from Two.
If you somehow did the following or equivalent, the last one would win out.
use One qw( temp );
use Two qw( temp );
That's why it's good to always list the subs you import. Don't use
use Foo; # Import default exports
Instead, use
use Foo qw( ); # Only import the listed exports. (None, in this case.)
If nothing else, it also makes it a lot easier to find subs and their documentation when maintaining the module.
The last one you compile wins, and use and require statements run in order from top to bottom (including any nesting inside modules that you include).
In this case, you have two module files, neither of which declare a package. Since they don't declare a package, they both use the default package main. Everything these modules define will show up in the main package.
Likewise, your program is also using the default package main, which is how is knows there is a temp subroutine. Since you loaded two.pm last, that's the definition that wins.
Now, let's fix up the code in your question because it doesn't actually work. Neither of those modules will load because neither returns a true value.
Both modules now have the same code because I can use the __FILE__ token to tell me which code ran:
one.pm:
sub temp { print 'From ' . __FILE__ }
1;
two.pm:
sub temp { print 'From ' . __FILE__ }
1;
temp.pl:
use lib qw(.);
use one;
use two;
temp();
Running this outputs the message from two.pm because that's the last one defined:
$ perl temp.pl
From two.pm
Run your program with warnings and you'll see there's a redefinition (which in this case is intentional):
$ perl -w temp.pl
Subroutine temp redefined at two.pm line 1.
From two.pm
The trick, then, is to ensure that your new code always comes last. One way to do this is to load the old module from the new one:
two.pm:
use one;
sub temp { print 'From ' . __FILE__ }
1;
I won't go any further with your example because I figure it's not your actual situation. I do write about these sorts of things in Effective Perl Programming though.
Yes. A use statement is equivalent to:
BEGIN { require Module; Module->import( LIST ); }
And Perl runs all compile time code (BEGIN blocks and use statements) in the order it appears (but before any runtime code is executed):
You may have multiple BEGIN blocks within a file (or eval'ed string); they will execute in order of definition.
What creates the subroutine in the current package is usually that module's import method, which will override any existing subroutines with those names at the time it runs.

writing reflective method to load variables from conf file, and assigning references?

I'm working with ugly code and trying to do a cleanup by moving values in a module into a configuration file. I want to keep the modules default values if a variable doesn't exist in the conf file, otherwise use the conf file version. There are lots of variables (too many) in the module so I wanted a helper method to support this. This is a first refactoring step, I likely will go further to better handle config variables later, but one step at a time.
I want a method that would take a variable in my module and either load the value from conf or set a default. So something like this (writing this from scratch, so treat it as just pseudocode for now)
Our ($var_a, $var_b ...);
export($var_a, $var_b ...);
my %conf = #load config file
load_var(\$var_a, "foo");
load_var(\$var_b, "$var_abar");
sub load_var($$){
my($variable_ref, $default) = #_
my $variale_name = Dumper($$variable_ref); #get name of variable
my $variable_value = $conf{$variable_name} // $default;
#update original variable by having $variable_ref point to $variable_value
}
So two questions here. First, does anyone know if some functionality like my load_var already exists which I an reuse?
Second, if I have to write it from scratch, can i do it with a perl version older then 5.22? when I read perlref it refers to setting references as being a new feature in 5.22, but it seems odd that such a basic behavior of references wasn't implemented sooner, so I'm wonder if I'm misunderstanding the document. Is there a way to pass a variable to my load_var method and ensure it's actually updated?
For this sort of problem, I would be thinking along the lines of using the AUTOLOAD - I know it's not quite what you asked, but it's sort of doing a similar thing:
If you call a subroutine that is undefined, you would ordinarily get an immediate, fatal error complaining that the subroutine doesn't exist. (Likewise for subroutines being used as methods, when the method doesn't exist in any base class of the class's package.) However, if an AUTOLOAD subroutine is defined in the package or packages used to locate the original subroutine, then that AUTOLOAD subroutine is called with the arguments that would have been passed to the original subroutine.
Something like:
#!/usr/bin/env perl
package Narf;
use Data::Dumper;
use strict;
use warnings;
our $AUTOLOAD;
my %conf = ( fish => 1,
carrot => "banana" );
sub AUTOLOAD {
print "Loading $AUTOLOAD\n";
##read config file
my $target = $AUTOLOAD =~ s/.*:://gr;
print $target;
return $conf{$target} // 0;
}
sub boo {
print "Boo!\n";
}
You can either call it OO style, or just 'normally' - but bear in mind this creates subs, not variables, so you might need to specify the package (or otherwise 'force' an import/export)
#!/usr/bin/env perl
use strict;
use warnings;
use Narf;
print Narf::fish(),"\n";
print Narf::carrot(),"\n";
print Narf::somethingelse(),"\n";
print Narf::boo;
Note - as these are autoloaded, they're not in the local namespace. Related to variables you've got this perlmonks discussion but I'm not convinced that's a good line to take, for all the reasons outlined in Why it's stupid to `use a variable as a variable name'

imported perl variable imports with no value

SOLVED: As it turns out, my problem was rooted in the fact that I was not putting a $ in front of DEBUGVAR in the #EXPORT_OK assignment and the "use config_global qw(config DEBUGVAR);" line. Since it raises no error, I had no way to know this was the issue. So, the fix is to place the proper syntax in front of your variables at these points.
So I am trying to get the hang of writing and importing perl modules. I don't know why it was made so difficult to do this, but I am having a great deal of trouble with this seeimingly trivial task. Here is the contents of my module:
package global_config;
use strict;
require Exporter;
our #ISA = qw(Exporter);
our #EXPORT_OK = qw(DEBUGVAR);
our ($DEBUGVAR);
our $DEBUGVAR = "Hello, World!";
return 1;
Here are the contents of my perl script that imports the module:
use strict;
use config_global qw(config, DEBUGVAR);
our %config;
our $DEBUGVAR;
print "variable imported with value: ".$DEBUGVAR;
The output is "variable imported with value:", and nothing else. My variable appears to be losing it's value. What am I doing wrong?
EDIT: After fiddling around a bit, and turning warnings on, I have isolated the issue to being that $DEBUGVAR is never actually imported. When I use it via $config_global:DEBUGVAR, it works as expected. The issue now is that it is not importing into the namespace. What gives?
I see several issues:
You should not use a comma in the qw() syntax. The qw takes each whitespace separated phrase and puts it in an array element.
These two are the same:
my #bar = qw(foo bar barfu); #No commas!
my #bar = ("foo", "bar", "barfu"); #Commas Required
If you're exporting a variable, you need to put the sigil in front of it.
You have:
our #EXPORT_OK = qw(DEBUGVAR);
It should be:
our #EXPORT_OK = qw($DEBUGVAR);
You should use the newer Exporter syntax:
Here's the newer Exporter Syntax:
package global_config;
use strict;
use warnings;
use Exporter 'import'; #Not "require". No need for "#ISA"
our #EXPORT_OK = qw(DEBUGVAR);
our $DEBUGVAR = "Hello, World";
1; #Makes no real difference, but you shouldn't say "return 1". Just standard.
Finally, what are you doing exporting variables? That's just a bad practice.
Exporting anything is now questioned -- even functions. It pollutes the user's namespace. (At least you're using #EXPORT_OKAY). Take a look at File::Spec. It uses fully qualified package names for its subroutines by default.
The variable in question is accessible via the full package name $global_config::DEBUGVAR, so there's no real need to export it.
What if everybody did it? Yes, you last heard of this excuse in kindergarten, but it applies here. Imagine if several modules exported $DEBUGVAR.
There are several ways around your quandary, but the best is to use object oriented Perl to help set this variable, and even allow users to change it.
package MyPackage;
use strict;
use warnings;
use feature qw(say);
sub new {
my $class = shift;
my $debug = shift; #Optional Debug Value
my $self = {};
bless $self, $class;
if (not defined $debug) {
$debug = "Hello, world!";
$self->Debug($debug);
return $self;
}
sub Debug {
my $self = shift;
my $debug = shift;
if (defined $debug) {
$self->{DEBUG} = $debug;
}
return $debug;
}
1;
To use this module, I simply create a new object, and Debug will be set for me:
use strict;
use warnings;
use MyPackage #No exporting needed
#Create an object w/ Debug value;
my $obj = MyPackage->new; #Debug is the default.
say $obj->Debug; #Prints "Hello, world!"
# Change the value of Debug
$obj->Debug("Foo!");
say $obj->Debug; #Now prints "Foo!"
#Create a new object with a different default debug
$obj2 = MyPackage->new("Bar!");
say $obj2->Debug; #Print "Bar!";
This solves several issues:
It allows multiple values of debug because each object now has its own values
There is no worry about namespace pollution or accessing package variables. Again, all you need is contained in the object itself.
It's easier to debug issues since the complexity is hidden inside the objects themselves.
It's the new preferred method, so you might as well get use to the syntax and be able to read object oriented Perl code. You'll be seeing it more and more.
While exporting variables from a package isn't necessarily a recommended practice, to do so, you need to use the actual name of the variable you are exporting. In this case it is $DEBUGVAR and not DEBUGVAR which would be the name of a subroutine.
In the script using the config module, you do not need to declare the $DEBUGVAR variable as our, since imported variables are exempt from strict vars.
You have gotten the name mixed up, it looks like:
use config_global ...
package global_config;
Though one would think that would issue warnings. Unless you are not using warnings...?
ETA:
our #EXPORT_OK = qw($DEBUGVAR);
^
Also, you have two declarations on that variable. You really need to use warnings when debugging, otherwise, you'll never get anywhere.
Are you sure you want a comma here:
use config_global qw(config, DEBUGVAR);
Also, you aren't exporting config, so it might work better as:
use config_global qw(DEBUGVAR);
I'd also remove the last our $DEBUGVAR; since it might set it to undef (or at least put it before the "use" line) -- I am not sure about this though.

Is there a way to "use" a single file that in turn uses multiple others in Perl?

I'd like to create several modules that will be used in nearly all scripts and modules in my project. These could be used in each of my scripts like so:
#!/usr/bin/perl
use Foo::Bar;
use Foo::Baz;
use Foo::Qux;
use Foo::Quux;
# Potentially many more.
Is it possible to move all these use statements to a new module Foo::Corge and then only have to use Foo::Corge in each of my scripts and modules?
Yes, it is possible, but no, you shouldn't do it.
I just spent two weeks to get rid of a module that did nothing but use other modules. I guess this module started out simple and innocent. But over the years it grew into a huge beast with lots and lots of use-statements, most of which weren't needed for any given run of our webapp. Finally, it took some 20 seconds just to 'use' that module. And it supported lazy copy-and-paste module creation.
So again: you may regret that step in a couple of months or years. And what do you get on the plus side? You saved typing a couple of lines in a couple of modules. Big deal.
Something like this should work:
http://mail.pm.org/pipermail/chicago-talk/2008-March/004829.html
Basically, create your package with lots of modules:
package Lots::Of::Modules;
use strict; # strictly optional, really
# These are the modules we want everywhere we say "use Lots::Of::Modules".
# Any exports are re-imported to the module that says "use Lots::Of::Modules"
use Carp qw/confess cluck/;
use Path::Class qw/file dir/;
...
sub import {
my $caller = caller;
my $class = shift;
no strict;
*{ $caller. '::'. $_ } = \*{ $class. '::'. $_ }
for grep { !/(?:BEGIN|import)/ } keys %{ $class. '::' };
}
Then use Lots::Of::Modules elsewhere;
use Lots::Of::Modules;
confess 'OH NOES';
Yes.
In Foo/Corge.pm
use Foo::Bar;
use Foo::Baz;
use Foo::Qux;
use Foo::Quux;
1; # Be successful
All that is left is to get the directory containing sub-directory Foo added to your library path (#INC). Alternatively, create Foo.pm and have it use the other modules. They would be in a Foo sub -directory beside Foo.pm.
If you think about it, all the complex Perl modules that use other modules do this all the time. They are not necessarily in the same top-level package (Foo in this example), but they are used just as necessarily.
While you could use Carp, and Path::Class and confess, and so on (as jrockway suggests), that seems like overkill from where I'm sitting.
[EDIT: My earlier solution involving use Lots::Of::Modules; had a subtle bug -- see bottom. The fix makes things a bit uglier, but still workable.]
[EDIT #2: Added BEGIN { ... } around the code to ensure that any functions defined are available at compile time. Thanks to jrockway for pointing this out.]
The following code will do exactly what jrockway's code does, only simpler and clearer:
In Lots/Of/Modules.inc:
use Carp qw/confess cluck/;
use Path::Class qw/file dir/;
0; # Flag an error if called with "use" or "require" instead of "do"
To import those 4 functions:
BEGIN { defined( do 'Lots/Of/Modules.inc' ) or die; }
Because we don't have a package Lots::Of::Modules; statement at the start of this file, the use statements will export into the caller's package.
We must use do instead of use or require, since the latter will only load the file once (causing failure if use Lots::Of::Modules; is called more than once, e.g. in separate modules used by the main program). The more primitive do does not throw an exception if it fails to find the file named by its argument in #INC, hence the need for checking the result with defined.
Another option would be for Foo::Corge to just re-export any items of interest normally:
package Foo::Corge;
use base 'Exporter';
BEGIN {
our #EXPORT_OK = qw( bar baz qux quux );
use Foo::Bar qw( bar );
use Foo::Baz qw( baz );
use Foo::Qux qw( qux );
use Foo::Quux qw( quux );
}
1;
(The 'use' statements can probably go outside the BEGIN, but that's where they were in the code I checked to verify that this worked the way I thought it did. That code actually evals the uses, so it has a reason for them to be inside BEGIN which likely doesn't apply in your case.)
using #EXPORT instead #EXPORT_OK , is more simple
Library is :
package mycommon;
use strict;
use warnings;
use base 'Exporter';
our #EXPORT = qw(test);
sub test {
print "this is a test";
}
1;
use it:
#!/usr/bin/perl
use strict;
use warnings;
use mycommon;
common::test()