Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl Module Creation - Undefined subroutine

I'm new in perl and I'm trying to do this exercise but it doesn't work.

This is my module that I created.

#!/usr/bin/perl 
use warnings;
use strict;

package Prepare;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw( clean my_print );

sub clean{
    return chomp($_[0]);
}

sub my_print{
    return print("The Results: $_[0]\n");
}

1;

And this my script test_lib.pl

#!/usr/bin/perl
use warnings;
use strict;

use lib '/home/foobar/code';
use My::Prepare;

print "Enter a word: ";
my $input=<STDIN>;

print "You entered: $varia";

clean($input);
my_print($input);

I get this error:

Undefined subroutine &main::clean called at ./test_lib.pl line 13,  line 1.
like image 987
James Gomez Avatar asked Dec 23 '22 01:12

James Gomez


1 Answers

When it comes to package naming, three things need to agree:

  • location and name of the package file

  • name in the package statement in the package file (the namespace)

  • the use statement for the package in the code that uses it

They need to "agree" as follows.

If the package declaration in its file is package My::Package; then the package need be used as use My::Package, and its file is Package.pm in the directory My.

This directory My itself need be in a location that the interpreter will search, or we need to inform it where to look. Custom packages are usually not in directories that are searched by default, which is what lib pragma is for: With your

use lib '/home/foobar/code';

I'd expect My directory, with Package.pm in it, to be in /home/foobar/code directory.

Then here is your example, with fixed names and with a few more adjustments.

File /home/foobar/code/My/Prepare.pm :

package My::Prepare;

use warnings;
use strict;

use Exporter qw(import);

our @EXPORT_OK = qw( clean my_print );

sub clean { chomp(@_); return @_ }

sub my_print { print "The Results: $_[0]\n" }

1;

And a script that uses this module

#!/usr/bin/perl
use warnings;
use strict;

use lib '/home/foobar/code';

use My::Prepare qw(clean my_print);

print "Enter a word: ";
my $input = <STDIN>;

print "You entered: $input";

my ($cleaned_input) = clean($input);
my_print($cleaned_input);

Please adjust paths above to your actual directory structure, by adding or removing path components as suitable. The name My:: in particular is sticking out.

A few notes.

  • there is no need for the "shebang" line (#!/usr/bin/perl) in a module

  • use of Exporter above is a bit more modern

  • I strongly recommend using @EXPORT_OK (instead of @EXPORT), so that all listed symbols must be specifically imported by the user of the module. That is just better for everybody

  • Unrelated to packaging but important: The clean sub returns a list, so we need to assign from it to a list; assigning to a scalar would end up assigning the number of elements of the list.

    So even with just one variable passed around we need those parenthesis to indicate the list assignment, my ($cleaned_input) = ..., so the list of scalars returned from the sub is assigned to the list of variables (in parenthesis) on the left-hand-side, one for one.

    Then, when a list with just one variable is returned it is assigned to the first variable listed in parens, as intended. Without the parens $cleaned_input would be assigned 1, the length of the returned list in this case.

like image 75
zdim Avatar answered Dec 31 '22 13:12

zdim