How can I take a reference to a Perl subroutine?

Pmarcoen picture Pmarcoen · Apr 6, 2010 · Viewed 13.1k times · Source

I'm having some trouble figuring out how to make a reference to a subroutine in an external module file. Right now, I'm doing this:

External file

package settingsGeneral;    
sub printScreen {
    print $_[0];
}

Main

use settingsGeneral;    
my $printScreen = settingsGeneral::printScreen;
&$printScreen("test");

but this result into an error: Can't use string ("1") as a subroutine ref while "strict refs" in use

Answer

Greg Bacon picture Greg Bacon · Apr 6, 2010

As noted in perlmodlib, you should start your module's name with an uppercase letter:

Perl informally reserves lowercase module names for 'pragma' modules like integer and strict. Other modules normally begin with a capital letter and use mixed case with no underscores (need to be short and portable).

One way to call a sub defined in another package is to fully qualify that sub's name when you call it:

SettingsGeneral::printScreen "important message\n";

If all you want is a reference to printScreen, grab it with the backslash operator

my $subref = \&SettingsGeneral::printScreen;

and call it with one of

&$subref("one\n");
&{$subref}("two\n");
$subref->("three\n");

You could create an alias in your current package:

*printScreen = \&SettingsGeneral::printScreen;
printScreen("another urgent flash\n");

Skip the parentheses (necessary because the sub in the current package wasn't known at compile time) by writing:

use subs 'printScreen';
*printScreen = \&SettingsGeneral::printScreen;
printScreen "the sky is falling!\n";

The Exporter module can do this custodial work for you:

SettingsGeneral.pm:

package SettingsGeneral;

use Exporter 'import';

our @EXPORT = qw/ printScreen /;

sub printScreen {
  print $_[0];
}

1;

main:

#! /usr/bin/perl

use warnings;
use strict;

use SettingsGeneral;

printScreen "foo!\n";