What is the "proper" way to bundle a required-at-runtime data file with a Perl module, such that the module can read its contents before being used?
A simple example would be this Dictionary module, which needs to read a list of (word,definition) pairs at startup.
package Reference::Dictionary;
# TODO: This is the Dictionary, which needs to be populated from
# data-file BEFORE calling Lookup!
our %Dictionary;
sub new {
my $class = shift;
return bless {}, $class;
}
sub Lookup {
my ($self,$word) = @_;
return $Dictionary{$word};
}
1;
and a driver program, Main.pl:
use Reference::Dictionary;
my $dictionary = new Reference::Dictionary;
print $dictionary->Lookup("aardvark");
Now, my directory structure looks like this:
root/
Main.pl
Reference/
Dictionary.pm
Dictionary.txt
I can't seem to get Dictionary.pm to load Dictionary.txt at startup. I've tried a few methods to get this to work, such as...
Using BEGIN block:
BEGIN { open(FP, '<', 'Dictionary.txt') or die "Can't open: $!\n"; while (<FP>) { chomp; my ($word, $def) = split(/,/); $Dictionary{$word} = $def; } close(FP); }
No dice: Perl is looking in cwd for Dictionary.txt, which is the path of the main script ("Main.pl"), not the path of the module, so this gives File Not Found.
Using DATA:
BEGIN { while (<DATA>) { chomp; my ($word, $def) = split(/,/); $Dictionary{$word} = $def; } close(DATA); }
and at end of module
__DATA__ aardvark,an animal which is definitely not an anteater abacus,an oldschool calculator ...
This too fails because BEGIN executes at compile-time, before DATA is available.
Hard-code the data in the module
our %Dictionary = ( aardvark => 'an animal which is definitely not an anteater', abacus => 'an oldschool calculator' ... );
Works, but is decidedly non-maintainable.
Similar question here: How should I distribute data files with Perl modules? but that one deals with modules installed by CPAN, not modules relative to the current script as I'm attempting to do.