Custom Local Packages in Perl

By: w1ldc4rd-w1z4rd
[ BACK... ]

Perl packages are an excellent way to organize code and create reusable modules. This post will guide you through creating custom packages in both the current folder and a subfolder, then loading them into your main program using FindBin for reliable path resolution.

Creating a Package in the Current Folder

Let’s start by creating a simple package called “MyUtils” in the same folder as our main script.

Create a file named “MyUtils.pm” with the following content:

package MyUtils;

use strict;
use warnings;

sub greet {
    my $name = shift;
    return "Hello, $name!";
}

sub square {
    my $num = shift;
    return $num * $num;
}

1;

This package contains two subroutines: greet and square.

Creating a Package in a Subfolder

Now, let’s create a package in a subfolder. First, create a directory called “lib” in your project folder.

Inside the “lib” folder, create a file named “MathOps.pm” with this content:

package MathOps;

use strict;
use warnings;

sub add {
    my ($a, $b) = @_;
    return $a + $b;
}

sub multiply {
    my ($a, $b) = @_;
    return $a * $b;
}

1;

Using Both Packages in Your Main Script

Create your main script “main.pl” in the project root directory:

#!/usr/bin/perl

use strict;
use warnings;
use FindBin qw($RealBin);
use lib ($RealBin, "$RealBin/lib");  # Add both directories to module search path
use MyUtils;
use MathOps;

my $greeting = MyUtils::greet("Bob");
print $greeting . "\n";

my $squared = MyUtils::square(5);
print "5 squared is: $squared\n";

my $sum = MathOps::add(3, 4);
print "3 + 4 = $sum\n";

my $product = MathOps::multiply(3, 4);
print "3 * 4 = $product\n";

Run the script, and you should see:

Hello, Bob!
5 squared is: 25
3 + 4 = 7
3 * 4 = 12

Importing Functions Without Package Names

You can also import functions from a package to use them without the package name prefix. Here’s how to modify “MyUtils.pm”:

package MyUtils;

use strict;
use warnings;
use Exporter qw(import);

our @EXPORT_OK = qw(greet square);
our %EXPORT_TAGS = (all => [@EXPORT_OK]);

sub greet {
    my $name = shift;
    return "Hello, $name!";
}

sub square {
    my $num = shift;
    return $num * $num;
}

1;

Now update your “main.pl” script:

#!/usr/bin/perl

use strict;
use warnings;
use FindBin qw($RealBin);
use lib ($RealBin, "$RealBin/lib");
use MyUtils qw(greet square);  # Import specific functions

my $greeting = greet("Charlie");  # No package name needed
print $greeting . "\n";

my $result = square(6);  # No package name needed
print "6 squared is: $result\n";

Run the script, and you’ll see:

Hello, Charlie!
6 squared is: 36

Key Points:

  1. Package files should have a .pm extension.
  2. The package name should match the filename (e.g., “MyUtils.pm” contains package MyUtils;).
  3. Always end your package file with 1; to ensure it returns a true value.
  4. Use use FindBin qw(RealBin);  *  * and *  * uselib(RealBin, “$RealBin/lib”); to add directories to Perl’s module search path reliably.
  5. Call package functions using the PackageName::function_name() syntax.
  6. To import functions for use without the package name prefix, use the Exporter module and specify which functions to export.

By following these steps and using FindBin, you can create and use custom Perl packages both in the current folder and subfolders with reliable path resolution. This approach helps organize your code and makes it more maintainable and reusable.

Copyright ©️ 2024 perl.gg