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

I'm having some dramas with understanding the referencing of enums from 'external' files. I think it's a combination of using the enum module and how scoping works in 'library' files... but I haven't been able to get my head 'round it...

I have a single, simple, 'library file' called 'slib.pl' that contains:

package slib; use enum qw(SM_UNK_REC SM_HDR_REC SM_TTL_REC); %SM_REC = ( SM_UNK_REC, "UNK", SM_HDR_REC, "HDR", SM_TTL_REC, "TTL" ); [...] sub ABC { my ($type) = @_; if ($type == SM_HDR_REC) { [...] } elsif ($type == SM_TTL_REC) { [...] }
Now, this all works quite happily for subs in the library - the enums are within the same physical file so they will be visible in the file's name space.

However, I'm having trouble 'seeing' the enums when I try to use a sub in the library from another program. For example I might have a program 'test.pl' like:

require 'slib.pl'; [...] $stat = &slib::ABC(SM_HDR_REC);
...and the SM_HDR_REC isn't translated properly. Initially, this makes sense, as there's nothing called 'SM_HDR_REC' in test.pl... even though I've 'require'ed the file that *does* include it.

So I try:

$stat = &slib::ABC($slib::SM_HDR_REC);
...and it still isn't seen. Finally, I try:

$stat = &slib::ABC(&slib::SM_HDR_REC);
...and it works. ...but I don't understand why the $slib::SM_HDR_REC is wrong. I thought the '&' was only for 'executing' subs and the '$' was used to 'reference' the location where some value is stored.

What can I do about seeing why the '$' doesn't work like I think it should? More simply, is there a better way to do what I'm trying to do, that is be able to use a symbolic name for a piece of data in both the library file AND programs that call the library file?

I'm using ActiveState Perl 5.6.1/Win98 and Perl 5.8.?/WinXP SP2.

Thanks for any pointers.

John

Replies are listed 'Best First'.
Re: Problems with the enum Module and File Scoping
by Errto (Vicar) on Sep 03, 2005 at 02:10 UTC
    I've never used enum but it seems to work roughly the same way that constant does - namely, it creates subroutines with the names that you give it, and these subroutines do nothing but return a value. Many of the experienced people here don't really like to use these modules, finding it easier to just use ordinary scalar variables instead which, as you note, are identified with a '$'. You're right that '&' is only for calling subroutines - what isn't so obvious is that that's how enum works. So in that case your code within slib.pl would be more like
    our $SM_UNK_REC = 1; our $SM_HDR_REC = 2; our $SM_TTL_REC = 3;
    Use "our" to declare these variables (instead of "my") so that they become visible to other packages, which is what you want. Now you can access these variables in just the way you tried:
    $stat = &slib::ABC($slib::SM_HDR_REC);

    By the way, a stylistic note - the ampersand in front of slib::ABC is almost definitely not needed.

    If you want, you can also make the constants available from the calling program directly by changing slib.pl to slib.pm and having it look a bit like this:

    package slib; use Exporter; our @ISA = qw/Exporter/; our @EXPORT_OK = qw/ABC $SM_UNK_REC $SM_HDR_REC $SM_TTL_REC/; ...
    and from your main program
    use slib qw/ABC $SM_UNK_REC $SM_HDR_REC $SM_TTL_REC/; $stat = ABC(SM_HDR_REC);
    or whatever you want.
      Ahhh.. 'our' is something I've never seen mentioned anywhere; nothing in the Camel book index, nor in the Llama book index on it... but how handy that's going to be :)

      Making the 'library' into a 'module' is the next step. I don't necessarily want to distribute it but it's probably (the proverbial) 'GoodThing(tm)' to implement these functions via a module, rather than a library; I've not built a module yet so I still have to study-up on that side of things, particularly as regards the exporting of data, subs, etc.

      Many thanks for the helpful suggestions though.


      John

Re: Problems with the enum Module and File Scoping
by ikegami (Patriarch) on Sep 03, 2005 at 02:12 UTC
    Enum probably creates constants which are special subs. If you want other modules to access them, export them using Exporter