Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

i have data stored in files as perl modules. an example file :
package test0; $data = { k0 => [ 1,2,3, ], k1 => [ 1,2,3, ], }; return (__PACKAGE__); 1;

Question(s) :
- is there no way to determine the name of the package without the use of the return?
- is there a way to determine the name of the hash that is in the package?

my code looks something like this :
#! use strict; use warnings; my $pmfile = shift @ARGV; my $pm = require "$pmfile"; no strict 'refs'; my $pckg = ${ $pm . "::data" }; use strict;

Questions :
- is my use of symbolic reference correct/appropriate?
- as you can see, the name of the package's data has to be hardcoded. is there an alternative?

thank you for your time and effort

Edited by Chady -- minor formatting, code tags.

Replies are listed 'Best First'.
Re: modules as data files
by dragonchild (Archbishop) on Oct 08, 2005 at 02:37 UTC
    package test0; use Exporter; our @ISA = qw( Exporter ); our @EXPORT_OK = qw( $data ); our $data = { .... }; 1;
    In your script ...
    #! use strict; use warnings; my $pmfile = shift @ARGV; my $pm = eval "use $pmfile '\$data';"; die $@ if $@; my $pckg = $data;

    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
      thanks for the quick reply.

      1) in the script, the variable $data is undeclared. doesn't it require an explicit package name?

      2) it appears that the script is still required to know the name of the hash in the module?

      3) i don't follow the use statement in the script. i can only use "files"; you are using a file _and_ a data structure. ( in fact, my perl copy reflects this as the $pm variable is uninitialized. )

        1. See my response to #2.
        2. Yes - this is part of the interface that the module publishes to the rest of the world. In fact, it's the whole reason the module exists. You had the same thing in your initial version. Mine just makes it a little more explicit.
        3. use Foo ('bar', 'baz'); is actually* implemented internally as so:
          BEGIN { require 'Foo.pm'; Foo->import( 'bar', 'baz' ); }
          The command that brings a file into your code is "require". "use" wraps require and adds a little something to it. Now, in my code, Exporter goes ahead and provides a import() method for you, expecting to use the @EXPORT_OK array to find stuff to bring from use'd namespace to the use-r. That's how $data makes it over from test0 to main.
        You might be confused by the funky syntax. That's because I'm doing an eval. You could replace the eval with the equivalent
        (my $filename = $pm) =~ s{ :: }{ / }gx; require "${filename}.pm"; $pm->import( '$data' );
        It's a bit harder to read, but you might put that into a subroutine called my_use() and call it that way. (There's a CPAN module that does this for you, but I don't remember its name off the bat.)

        * Well, not exactly, but the exact details would only get in the way.


        My criteria for good software:
        1. Does it work?
        2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
Re: modules as data files
by ioannis (Abbot) on Oct 08, 2005 at 06:51 UTC
      well, just kick me! i had a feeling the answer was embarassingly straightforward

      your answer of having the module return the hash solves both problems of :

      - knowing the package name

      - knowing the hash name

      thanks although i'm _really_ embarrassed! ( sorry to bother ya'll)