4

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.
zdim
  • 64,580
  • 5
  • 52
  • 81
James
  • 77
  • 6
  • 1
    Your package is called `Prepare`, not `My::Prepare`. Change `use My::Prepare;` to `use Prepare;` – GMB Jan 30 '19 at 03:43
  • Questions: Where is the module's file, in relation to the script (and/or to the path in `use lib`)? What is the name of that (module's) file? – zdim Jan 30 '19 at 03:44
  • `package Prepare;`, `use My::Prepare;`... one of those is wrong. – Shawn Jan 30 '19 at 03:46

1 Answers1

10

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.

ikegami
  • 367,544
  • 15
  • 269
  • 518
zdim
  • 64,580
  • 5
  • 52
  • 81