Re: Custom Module question
by davido (Cardinal) on Dec 03, 2014 at 21:44 UTC
|
The warning about uninitialized value is because in line 6 of the code you posted you set $name to contain nothing, and then in line 8 of the code you posted, you call printname($name). As the printname function executes, it attempts to print "Hello $name\n", where $name is empty (or undef), and this throws a warning.
Later when you call printname("John"), it actually works, because the parameter you pass in is not empty; it contains "John".
There are other issues, such as calling printname from your package main without your printname.pm module actually exporting the subroutine. But apparently your actual usage is not exactly as described, because you didn't mention that error. If you are seeing that error but simply not mentioning it, you should look at Exporter for solutions.
Additionally, you really should be using lexical variables in your subroutine that are scoped to the subroutine itself, not to the entire file: my ($name) = @_; would be a good start.
| [reply] [d/l] [select] |
|
|
Undefined subroutine &main::printname called at testmodule.pl line 8.
in the last line of the error output shown.
As a general thing I prefer to use an explicit package instead of Exporter to avoid name clashes and make the province clear.
Perl is the programming world's equivalent of English
| [reply] [d/l] |
|
|
| [reply] |
Re: Custom Module question
by toolic (Bishop) on Dec 03, 2014 at 21:31 UTC
|
use warnings;
use strict;
use lib "C:/Perl64/lib/printname";
use printname;
printname::printname("John");
| [reply] [d/l] |
Re: Custom Module question
by Perlbotics (Archbishop) on Dec 03, 2014 at 21:43 UTC
|
The mainOne (thanks davido ;-) problem is, that sub printname lives in the package printname::.
Your main program lives in the package main::.
To access sub printname() from your main program, you either need to access it like so printname::printname("John") or by exporting sub printname() from package printname::
into package main::. The latter allows it to work as you expected in your example.
The module Exporter helps you to import the prinname::printname() to main::printname(). BTW, lowercase package names are reseved for pragmas.
An introduction to writing modules can be found in perlmod, etc.
| [reply] [d/l] [select] |
|
|
That may be the main problem in the code he posted, but it's not the problem he's seeing when he runs his program (which must not be identical to what is posted), or he would have asked about that rather than the warning. However, the reason for the warning he asks about in his question is pretty easy to spot.
:)
Update: GrandFather correctly pointed out that I missed the second message, and thus didn't notice that one of his problems is the failure to either export or fully qualify the function.
| [reply] |
Re: Custom Module question
by davido (Cardinal) on Dec 04, 2014 at 05:39 UTC
|
I just wanted to mention, this is probably a better way to do it.
First, the module:
package PrintName;
use strict;
use warnings;
use parent qw/ Exporter /;
our @EXPORT_OK = qw/ print_name /;
sub print_name {
my($name) = @_;
print "Hello, $name\n";
}
1;
The camel-casing of the package name is more of a style issue, but seems to be a fairly common practice. We're subclassing Exporter, but only exporting the function on-demand. The underscore casing of the subroutine name is purely a style issue, and there's no real community consensus of whether or not it should be applied to function names, but I tend to prefer it. We're using a lexically scoped variable for the parameter of the subroutine also, and the scope is constrained to the sub. We're not invoking the subroutine from within the module, and particularly not doing it with an undefined value.
And here's how the caller might look:
package main;
use strict;
use warnings;
use lib "C:/Perl64/lib/printname";
use PrintName qw/ print_name /;
print_name("John");
The use lib ... construct is often seen as the second part to a FindBin idiom. ...just something to keep in mind.
In the caller, we're explicitly importing print_name, and then calling it.
| [reply] [d/l] [select] |
|
|
Thanks for the comments, this is great here is my updated code
module
package Printname;
use strict;
use warnings;
use parent qw/ Exporter /;
our @EXPORT_OK = qw/ print_name /;
sub print_name {
my($name) = @_;
print "\nHello, $name\n";
}
1;
script
#!/usr/bin/perl
package main;
use strict;
use warnings;
use lib "C:/Perl64/lib/printname";
use lib "C:/Perl64/site/lib/printname";
use PrintName qw/ print_name /;
print_name("John");
error
C:\Scripts>perl testmodule.pl
Undefined subroutine &main::print_name called at testmodule.pl line 11.
line 11 is print_name("John");
I tried calling the subroutine from within the module itself but it didn't make a difference. Thanks
| [reply] [d/l] [select] |
|
|
Thanks for fixing your formatting. The other response is correct: "use PrintName", vs package Printname... these things are case sensitive.
Also, if I recall, Windows filenames are not case-sensitive, but many other operating systems are. For all those OS's that are case-sensitive, when your module starts out with package PrintName;, the file it lives in should usually be named PrintName.pm, not printname.pm. In your environment case sensitivity of filenames is probably not an issue, but someday you'll discover the rest of the world and realize what you've been missing. ;)
| [reply] [d/l] [select] |
|
|
|
|
|
|
|
Why didn't you format it using <code>...</code> tags? I can't read it the way it is.
Please see Writeup Formatting Tips for details. Once you've updated your post with code tags I'll look it over if I can still get to it.
| [reply] [d/l] |
|
|
# package Printname;
package PrintName;
poj
| [reply] [d/l] |
Re: Custom Module question
by wazat (Monk) on Dec 03, 2014 at 22:37 UTC
|
While this doesn't directly address your question, I notice that you seem to be mixing array/list syntax with scale syntax. Something prefixed with an '@' is an array. Sets of things in parantheses are often lists. Scalars, like a simple string, are prefixed with '$' (note that the individual elements of an array are scalars, so to refer to the first element of an array you use $arrname[0]). I suspect you want something like:
my $name = '';
printname($name);
sub printname {
my $name = shift;
print "Hello, $name\n";
}
I've used shift to remove the 1st element of the subroutine arguments array and put it into $name. You could also use my $name = $_[0]. Use my for lexical scoping for the variable $name, that way, while there may be many scalars named $name, the one in the subroutine is distinct from any others. If you don't scope your variables wisely, your progams can quickly become unmaintainable. | [reply] [d/l] [select] |
|
|
| [reply] [d/l] |
Re: Custom Module question
by AnomalousMonk (Archbishop) on Dec 03, 2014 at 23:28 UTC
|
See also the recent and somewhat related sub running on use statement. (I see a hint of relation due to the calling of printname() immediately from the module within which it is defined.)
| [reply] [d/l] |