Error "Undefined subroutine" & module references

M

mailbox

Given the program below:

#!/usr/bin/perl
use ATrial;
$D = ATrial::SomeSubr();
print "|$D|\n";

I find that if I remove the "ATrial::" from
the assignment statement, I get a runtime
error "Undefined subroutine &main::SomeSubr called..."

According to the "Perl Cookbook," page 446, I should
be able to dispense with that prefix if I have
the "use" statement. What's going on?

The module ATrial.pm is in the same directory,
and is as follows:

package ATrial;
sub SomeSubr () {
return "HELLO";
}
1;

The really odd thing is that I've been cruising along for
several hundred lines one directory level up from where
I am now in a project in which I've created a couple of
modules and referenced stuff in them from a dozen scripts.
I don't see any obvious difference in the usage there.
Using -I with pathnames in the command line to make things
more explicit has had no effect.
 
P

Paul Lalli

Given the program below:

#!/usr/bin/perl
use ATrial;
$D = ATrial::SomeSubr();
print "|$D|\n";

I find that if I remove the "ATrial::" from
the assignment statement, I get a runtime
error "Undefined subroutine &main::SomeSubr called..."

According to the "Perl Cookbook," page 446, I should
be able to dispense with that prefix if I have
the "use" statement. What's going on?

I don't have my copy of the Cookbook on me, but I have to believe
you're misinterpreting what it's telling you.

You can only call another module's subroutines without fully qualifying
them if that module exported that subroutine name, and your current
package imported it. The 'use' statement does import all of ATrial's
exports. However...
The module ATrial.pm is in the same directory,
and is as follows:

package ATrial;
sub SomeSubr () {
return "HELLO";
}
1;

We see here that ATrial never exported SomeSubr. In order for this to
work the way you wanted, you have to add the following lines under
'package ATrial;' :
use Exporter;
our @ISA = qw/Exporter/;
our @EXPORT = qw/SomeSubr/;

Alternatively, you can make ATrial simply *offer* to export SomeSubr,
at which point your main package has to specifically request it. To do
this, replace the last line above with:
our @EXPORT_OK = qw/SomeSubr/;
and change the 'use' statement in the main file to:
use ATrial qw/SomeSubr/;

For more information on exporting and importing, please read:
perldoc Exporter

Paul Lalli
 
M

mailbox

Paul said:
(e-mail address removed) wrote:
I don't have my copy of the Cookbook on me, but I have to believe
you're misinterpreting what it's telling you.


You're right. Reading further, I see it shows how to use the lines of
code you indicated. But that's a lot of stuff, and how did I get this
far without needing it? I looked at my earlier code and noticed this:
My key module -- I even call it Reusables.pm -- doesn't have a package
statement! So going back to the example in my posting, I removed the
package statement in ATrial.pm, and the program worked without the
explicit reference "ATrial::". Apparently Perl is giving me some
undocumented latitude in external referencing, and I can only wonder
where the boundaries are.
 
P

Paul Lalli

You're right. Reading further, I see it shows how to use the lines of
code you indicated. But that's a lot of stuff, and how did I get this
far without needing it? I looked at my earlier code and noticed this:
My key module -- I even call it Reusables.pm -- doesn't have a package
statement! So going back to the example in my posting, I removed the
package statement in ATrial.pm, and the program worked without the
explicit reference "ATrial::". Apparently Perl is giving me some
undocumented latitude in external referencing, and I can only wonder
where the boundaries are.

Any piece of code that does not have an explicit package statement in
effect is in package main::. Therefore, when you removed the package
ATrial; statement, that code in ATrial.pm became part of the main::
package as well. When you call a subroutine without a fully-qualified
name (ie, without the package label), it is taken to mean "the current
package". Since both your main file and ATrial.pm are in the same
package, the code executes without errors. You would have seen the
same result if you'd added 'package ATrial;' to your main file, rather
than removed it from ATrial.pm

When you 'use Atrial;', you're really doing two distinct things:
require 'Atrial.pm';
Atrial->import();

The first line simply loads the code in Atrial.pm. The second line
attempt to import from the Atrial class. Nothing about the first line
says that Atrial.pm has to contain a package named Atrial::. And as
for the second line, if no such class exists, the import() call is
silently ignored (I believe via a call to the "empty" core level
import() function, but I could be wrong on that).

Check out
perldoc -f use
perldoc -f require
for more information

Paul Lalli
 
M

mailbox

Jim said:
The default package is "main". So without a package name, any external
file included by your program with 'do', 'require', or 'use' becomes
part of the main package and may be referenced without a qualifier
(unless of course 'use strict' is in effect).

Yes, I see now...except that my only available reference, "The Perl
Cookbook," doesn't mention "use" in this context. Thanks to everyone.
 
P

Paul Lalli

Yes, I see now...except that my only available reference, "The Perl
Cookbook," doesn't mention "use" in this context. Thanks to everyone.

1) The Cookbook is not a reference. It is a list of recipees.
2) The Cookbook is by no means your "only available" reference. You
obviously have access to the internet. You also obviously have access
to a Perl distrobution.

http://search.cpan.org/dist/perl/pod/perlfunc.pod#use
or from the command line:
perldoc -f use

Paul Lalli
 
M

mailbox

Paul said:

Well, that Web page -- at least that section of it -- was not written
for mortals like me; it has no practical value for an applications guy.
As for perldoc, I get an error message
No documentation found for "perlfunc".
Maybe I should talk to our sysadmin about that. Or, I'll just put it on
my wish list for when we migrate to the new system shortly.
 
P

Paul Lalli

Well, that Web page -- at least that section of it -- was not written
for mortals like me; it has no practical value for an applications guy.

I disagree. Perhaps you could let us know what part of that
documentation is unclear to you, and someone here could clarify it?
As for perldoc, I get an error message
No documentation found for "perlfunc".
Maybe I should talk to our sysadmin about that.

Yes. Whoever installed perl on your system neglected to install the
corresponding documentation.

Paul Lalli
 
G

Gunnar Hjalmarsson

Paul said:
1) The Cookbook is not a reference. It is a list of recipees.
2) The Cookbook is by no means your "only available" reference. You
obviously have access to the internet. You also obviously have access
to a Perl distrobution.

True, but isn't it rather unusual to use() a file with Perl code that is
not a module?
 
P

Paul Lalli

Gunnar said:
True, but isn't it rather unusual to use() a file with Perl code that is
not a module?

I don't know. I don't think I've ever included code from an external
file that wasn't a module. I guess maybe I'd do a simple 'require'
instead? But 'use' on a file that doesn't define a module (and
therefore does not have an associated import() method) is really just
BEGIN { require '...' } anyway, so I'm not sure I see how it would
hurt.

Paul Lalli
 
G

Gunnar Hjalmarsson

Paul said:
I don't know. ... I'm not sure I see how it would hurt.

I didn't intend to imply that it might hurt, but the absence in the
cookbook of use() in the context of including non-module files of Perl
code might be non-accidental. ;-)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top