This is with regard to my previous question
Hold Subroutine response and set to variable in Perl
The statement Module::thesub("hello")
worked in Module.pm but fails if I move it to main.pl
main.pl
#!/usr/bin/perl
use strict;
use warnings;
use Module;
Module::thesub("hello");
Module.pm
#!/usr/bin/perl
use strict;
use warnings;
package Module;
sub thesub {
state $stored;
$stored = shift if #_;
return $stored;
}
my $testvar = thesub();
print $testvar;
1;
I get this error
Use of uninitialized value $testvar
which means the variable $testvar has no value.
How can I fix this?
Statements in a module run when the module is loaded, at use Module;. At that time thesub() still wasn't called with an argument and $stored in it is undefined. So that is what $testvar gets when it's assigned and the warning is emitted when it's printed.
The $testvar can be used in main
use strict;
use warnings;
use Module;
Module::thesub("hello");
my $testvar = Module::thesub();
even though I am not sure from the question what the purpose of this is.
Remove the assignment and print of $testvar from the module. Note that you'll also need use feature 'state'; at the beginning of the module, to enable the feature pragma.
A few comments on the module you show
No need for #!/usr/bin/perl, as a module is generally not meant to be run
The package Module; is commonly the first line
While what you have works, consider making symbols from the module available to the calling code, so that it can import them and simply say thesub(). A common way is
package Module;
use warnings;
use strict;
use Exporter qw(import);
our #EXPORT_OK = qw(thesub);
sub thesub { ... }
1;
and in the main
use Module qw(thesub);
thesub("hello");
See Exporter for starters and search SO, where there are great many posts on this.
Related
I have a module called Utilities.pm. It exports a subroutine called dummy_method.
package Foo::Utilities;
use strict;
use vars qw($VERSION #ISA #EXPORT #EXPORT_OK);
require Exporter;
#ISA = qw(Exporter);
#EXPORT = qw(dummy_method);
sub dummy_method {
# do things
}
I have a Perl script that uses the dummy_method subroutine:
use strict;
use warnings;
use Foo::Utilities qw('dummy_method');
my $foo = Foo::Utilities::dummy_method("foo");
print("$foo\n");
Executing that script throws an export error:
"dummy_method" is not exported by the Foo::Utilities module
Can't continue after import errors at /home/me/foo.pl line 3
BEGIN failed--compilation aborted at /home/me/foo.pl line 3.
I'm confused because I am explicitly exporting that subroutine with #EXPORT = qw(dummy_method);. How do I use dummy_method in another script?
Some people are obsessed with using qw for import lists, even if there is only one element. I think this makes others think this is a requirement, when it is just one way of making a list.
use Foo::Utilities qw('dummy_method');
says to import a method called 'dummy_method', not dummy_method, just like print qw('dummy_method') prints 'dummy_method', not dummy_method.
Try instead:
use Foo::Utilities 'dummy_method';
or, if you must:
use Foo::Utilities qw(dummy_method);
Though since you are exporting it by default, you could just do:
use Foo::Utilities;
Or, since you are calling it as Foo::Utilities::dummy_method, not even export it by default:
use Foo::Utilities ();
The code you have written, with the modification suggested by ysth, works correctly. The only remaining possibility that I can think of is that you have named or located your module incorrectly
use Foo::Utilities 'dummy_method'
will load a file called Foo/Utilities.pm where the Foo directory is in one of the paths in your #INC. It is a common error to omit the initial directories that must be in the path to the module, and you do say that your module is called just Utilities.pm
There must also be a Foo/Utilities.pm that behaves differently, otherwise the use statement would fail even to find the file
I have written your code in more modern Perl. This also works
Foo/Utilities.pm
package Foo::Utilities;
use strict;
use warnings 'all';
use Exporter 'import';
our #EXPORT = qw(dummy_method);
sub dummy_method {
print "dummy_method()\n";
'do things';
}
main.pl
use strict;
use warnings;
use Foo::Utilities 'dummy_method';
my $foo = dummy_method('foo');
print("$foo\n");
There is no need for using vars any more, and it has been better to import the import method from Exporter (instead of inheriting it) since Perl v5.8.7
I'm writing a basic program whose core logic is split across several project-specific modules for cleanliness (keeping subroutines organised by their purpose in the program's logic).
Suddenly had trouble exposing an option from the main package in one of the modules, and using the our statement appeared to have no effect.
For brevity, I'll copy+paste an isolated test case I wrote to examine this behaviour:
main.pl
#!/usr/bin/perl
use warnings;
use strict;
use File::Basename;
# The variable to be read by the module.
our $verbose = 1;
# Load Output.pm from directory
use lib dirname "$0";
use Output;
write_message "Hello, world\n";
Output.pm
package Output;
use warnings;
use strict;
use parent "Exporter";
our #EXPORT = qw(write_message);
# Should be imported?
our $verbose;
sub write_message {
print $_[0] unless !$verbose;
}
1;
Expected result: "Hello, world"
Actual result: Dead silence
It's quite possible that what I'm trying to achieve isn't even possible in Perl, as this isn't the intended use of modules (and heck, I understand why that'd be the case).
I'm still quite new to Perl and there are some things I'm struggling to wrap my head around. I've seen people recommend using the our declarator to expose a variable across packages, but I can't understand why this isn't working.
PS: If anybody knows a better approach to splitting an app's program-specific logic between modules, I'd appreciate some pointers too. :) But first and foremost, I'd prefer to learn why our-ing a variable isn't working.
An our statement just creates a package variable (whereas my creates a lexical variable). It has nothing to do with exporting
The best option is probably to declare the variable in the Output package and access it as $Output::verbose elsewhere. Like this
main.pl
#!/usr/bin/perl
use strict;
use warnings;
use File::Basename;
use lib dirname $0;
use Output;
$Output::verbose = 1;
write_message "Hello, world\n";
Output.pm
package Output;
use strict;
use warnings;
use Exporter 5.57 'import';
our #EXPORT = qw/ write_message /;
our $verbose;
sub write_message {
print $_[0] if $verbose;
}
1;
Note that I have also removed the incorrect quotes from around $0, and ever since version 5.57 of Exporter it has been possible (and preferable) to import it's import subroutine instead of subclassing it
our declares a package variable in the current package. The one in main.pl refers to $main::verbose; the one in Output.pm refers to $Output::verbose.
You can use the full name $main::verbose to access the variable from anywhere, but you can't really "export" it because exporting refers to making symbols accessible to users of your module. You're trying to do the opposite.
What does
use Cwd qw();
mean in perl?
I know qw gives quotes to each elements inside ()
But what about this case?
The qw() is a fancy way of writing an empty list. Doing () would be two characters shorter.
Passing an empty list to use is important to avoid importing. From the use documentation:
If you do not want to call the package's import method (for instance, to stop your namespace from being altered), explicitly supply the empty list
E.g. by default, the Cwd module exports getcwd. This doesn't happen if we give it the empty list:
use strict;
use Cwd;
print "I am here: ", getcwd, "\n";
works, but
use strict;
use Cwd ();
print "I am here: ", getcwd, "\n";
aborts compilation with Bareword "getcwd" not allowed while "strict subs" in use.
I believe that since qw() after use Module is for importing subroutines, when left empty it simply loads the module but doesn't import any subroutines into the namespace.
For example this throws an error since getcwd is not imported:
#!/usr/bin/perl
use warnings;
use strict;
use Cwd qw();
my $dir=getcwd;
But I'm not sure if this is the answer you was looking for..!
Usually it "imports" commands so you don't have to create an object and call the function on them.
Example (from perlmonks):
#without qw
use CGI;
my $q = CGI->new();
my $x = $q->param('x');
#with qw
use CGI qw/:standard/;
my $x = param("x")
Source: http://www.perlmonks.org/?node_id=1701
Most modules have import groups like :all or :standard also.
This is usex.pl:
#use strict;
require 'x.pl';
print $x;
Here is x.pl:
#use strict;
our $x = 99;
1;
It runs fine as shown. If I uncomment the line to use strict in usesx.pl, I get
Global symbol "$x" requires explicit package name
The use or not of strict in x.pl seems not to matter (unless I drop the 'our' keyword, but I'm not interested in that.)
I'm fairly new to Perl. Why does strict make $x not visible in the main script, and what is the normal solution to this?
Two reasons.
The error happens at compile-time, before require is ever executed. That's easy to fix using BEGIN.
our is lexically-scoped, and it's in a different lexical scope (file or block) than the print, so it's no longer in effect.
The whole approach is fundamentally bad. Here's one better way:
package MyConfig;
use strict;
use warnings;
use Exporter qw( import );
our #EXPORT = qw( $x );
our $x = 123;
1;
use strict;
use warnings;
use MyConfig;
print "$x\n";
Hehe, our is not easy to grok as it mixes the concepts of global and lexical scope. What it does is exempting a global variable from the strict 'vars' pragma and allowing unqualified access to it within its scope, which is the enclosing block, or the end of the current file, whatever comes first. Read the full (but brief) story in the manual, which is also accessible by saying perldoc -f our on the command line.
As for your script, you can verify the truthfulness of the words in the manual by modifying the variable accessor to use a package-qualified name:
use strict;
require 'x.pl';
print $main::x;
I want use some packages and some pragmas in all my programs, like:
use 5.014;
use warnings;
use autodie;
use My::ModuleA::Something;
use ModuleB qw(Func1 Func2);
I don't want repeat myself in every module, so looking for a way how to make one package e.g. My::Common what will contain the above packages and in my programs do only:
use My::Common;
say Func1("hello"); #say enabled and Func1 imported in the My::Common
how to achieve this?
The was read preldoc -f use and perldoc perlmodlib so i think I must "somewhat" to do this with BEGIN plus require&import, but absolutely don't know how.
UPDATE: I'm already tried the basic things.
With require - my prg.pl program.
require 'mymods.pl';
$var = "hello";
croak "$var\n";
mymods.pl contain
use strict;
use feature 'say';
use Carp qw(carp croak cluck);
1;
DOES NOT WORKS. Got error:
$ perl prg.pl
String found where operator expected at prg.pl line 3, near "croak "$var\n""
(Do you need to predeclare croak?)
syntax error at prg.pl line 3, near "croak "$var\n""
Execution of prg.pl aborted due to compilation errors.
with "use My":
use My;
$var = "hello";
croak "$var\n";
my My.pm
package My;
use strict;
use feature 'say';
use Carp qw(carp croak cluck);
1;
DOES NOT WORKS either. Got the same error.
Any working idea?
I'd go with this:
package My::Common;
use 5.14.0;
use strict;
use warnings;
use autodie;
use Carp qw(carp croak cluck);
sub import {
my $caller = caller;
feature->import(':5.14');
# feature->import('say');
strict->import;
warnings->import;
## autodie->import; # <-- Won't affect the caller side - see my edit.
{
no strict 'refs';
for my $method (qw/carp croak cluck/) {
*{"$caller\::$method"} = __PACKAGE__->can($method);
}
}
}
1;
Please correct me if I'm wrong, or there's a better way.
EDIT:
Sorry, I was wrong in using autodie->import...
This one should work, but it assumes that you always call My::Common from the main package:
package My::Common;
# ...
sub import {
# ...
strict->import;
warnings->import;
{
package main;
autodie->import;
}
# ...
}
So, of course, it's much safer and simpler to add a use autodie; to each script:
use My::Common;
use autodie;
# ...
It's actually fairly simple, if you override your "common" module's import method. See the source of chromatic's Modern::Perl module for an example of exporting pragmas.
For re-exporting things defined in other modules, I seem to recall that $export_to_level (see the Exporter docs, although it's not explained all that clearly) should do that, although I can't find any good examples at the moment. Another option would be Pollute::persistent, although I haven't used it, don't know anyone else who's used it, and can't say how stable/solid it's likely to be. If it works, though, it's probably the quickest and easiest option.
I've just noticed a module called rig in CPAN. Try it out.