http://www.perlmonks.org?node_id=959066

perl-diddler has asked for the wisdom of the Perl Monks concerning the following question:

Below is, what I think is the pertinent code, -- I'm trying to divide an old prog into modules/packages.
It was all global vars all over the place, and trying to tighten up the interfaces is causing a few problems....
Like the following -- am trying to export the vars and necessary routines in EXPORT, and use Exporter...
But the import in the next package doesn't work.
Now I've tried it with a plain 'import Debug' (no qw), and with/without the following BEGIN -- why that doesn't work is beyond me.
Am beginning to think perl 5.14 is broken...
So many progs that worked under 5.12 won't work under 5.14... what a disaster!..
That's been happening at each of the last few releases
5.8->5.10 broke several (including this one, which was why I decided to rewrite it...but haven't ever gotten it working again...and am now up to 5.14...).
5.10->5.12 -- more progs broke, 5.12->5.14 -- more progs broke...
Seems like one can't upgrade perl and expect any stability these days ;-/.


Anyway, line with debug @ 119 is marked below...
For those that want complete code. I'll post it in a followup, but wanted to post the snippet that was most relevant (I thought), here so this post wouldn't be overwhelming...
I'm clueless when it comes to using Exporter except how documented in the perldoc -- and EXPORT isn't even documented anymore... (?!?)...
*sigh*....
How am I supposed to export vars and subs out of 1 routine to another?
Thanks!
-linda
package Debug;{ use Readonly; sub RO(\[$@%]@) {goto &Readonly}; use Exporter 'import'; our @ISA = qw (Exporter); our @EXPORT=qw( Debug DEBUG_OPS $Filename2Fields $Halt_on_Error); my %dop = ( Filename2Fields => 1, HaltOnError => 2, ); sub _flagval { return $dop{$_[0]} } our $Filename2Fields = $dop{Filename2Fields}; our $HaltOnError = $dop{HaltOnError}; our $DEBUG_OPS = 0 | $Filename2Fields | $HaltOnError ; sub Debug($$) { my ($what, $str)=@_; if ($what & $DEBUG_OPS) { print STDERR $str; } } } ; package Transcode_plug;{ import Debug qw{Filename2Fields}; BEGIN {*Filename2Fields = \$Debug::Filename2Fields;} import Vars; use Exporter; our @ISA = qw(Exporter); our @EXPORT=qw( album album_artist artist freeDB_DiskID genre trknum trktitle year push_ar +ginfo get_bin_path ); sub get_fieldAR_from_filename($) { my $file=$_[0]; Debug($Filename2Fields,"get_fieldAR_from_filename($file)\n"); + <<---------- # line 119 my ($trknum, $trktitle, $artist, $album_artist, $genre, $year,$freeDB_DiscID); my ($rest,$tt_a, $aa_g_y);
The above gives: </code> > cnvWav2Flac Variable "$Filename2Fields" is not imported at ./cnvWav2Flac line 119.

Replies are listed 'Best First'.
Re: can't import using exporter
by chromatic (Archbishop) on Mar 12, 2012 at 07:05 UTC

    Do you mean:

    package Transcode_plug { use Debug qw{$Filename2Fields}; use Vars; ... }

    Let use handle the import for you, as it'll load the package and perform the importing during compilation time. Also remember the sigil.


    Improve your skills with Modern Perl: the free book.

      But "use" requires the package to be defined in an appropriately named separate file. If the Debug package is defined in the same file as Transcode_plug, then it needs to be import.

      It might be a good idea to do the import in a BEGIN block though, to ensure it happens at the same stage that use would have done it.

      The other alternative (as discussed in another thread recently) would be for the Debug package to include the following line:

      BEGIN { $INC{+__PACKAGE__}=__FILE__ }

      This will allow Transcode_plug to use Debug even though Debug isn't defined in a separate file.

      perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
        Actually, it needs to be
        package FOO::BAR; BEGIN {::$INC{FOO/BAR.pm}=1};
        You can't use __PACKAGE__ because it would be FOO::BAR -- not a pathname, and there is no file, so '1' (true) is fine.

        looks all better if you turn it into a 'use mem' statement' by adding a dummy package 'mem' first:

        {package mem; [#1] BEGIN{$::INC{'mem.pm'}=1} #1: '#' present if in separate file 1}
        After that's defined, then you can simply:
        { package Dbg; use mem &{sub(){$::INC{'Dbg.pm'}=1}}; use warnings; use strict; our @EXPORT; our $FRE; use mem &{sub(){$FRE = qr{:([^:]+)$} } }; use mem &{sub(){our @EXPORT = qw(Tracing Dumping Trackback DDump TPe +) } };
        Note the '@EXPORT line -- this is required to make EXPORT work in 5.14 as one would expect. I don't remember this being the case at some previous point in time. But this is what was wrong with the original program. @EXPORTS in the original and 'Exporter' (maybe Exporter was changed), don't work at 'BEGIN/start' time, so if you use strict; nothing you export will be considered "legal"...

        my 'use mem' module (all 2-3 lines of it!), is short for memorize this NOW for use in following code, or for the INC statements, use the memory cache for this routine and don't go to disk unnecessarily.

        FWIW -- the original prog mentioned here, now works (though it looks quite different).

        The single ~1600 line program has 17 classes and included 3 packages that can easily be re-integrated to run as 1 prog/file.

        I just tried that, but now get:
        Can't locate Debug.pm in @INC (@INC contains: /usr/lib/perl5/site_perl +/5.14.2/x86_64-linux-thread-multi /usr/lib/perl5/site_perl/5.14.2 /us +r/lib/perl5/vendor_perl/5.14.2/x86_64-linux-thread-multi /usr/lib/per +l5/vendor_perl/5.14.2 /usr/lib/perl5/5.14.2/x86_64-linux-thread-multi + /usr/lib/perl5/5.14.2 /usr/lib/perl5/site_perl/5.14.2/x86_64-linux-t +hread-multi /usr/lib/perl5/site_perl/5.14.2 /usr/lib/perl5/site_perl +.) at /Audio/scripts/cnvWav2Flac line 107. Transcode_plug::BEGIN() called at /Audio/scripts/cnvWav2Flac l +ine 107 eval {...} called at /Audio/scripts/cnvWav2Flac line 107 BEGIN failed--compilation aborted at /Audio/scripts/cnvWav2Flac line 1 +07.
        Here, BTW, is the complete prog. Tried to post it earlier as a response, but it wouldn't let me create a response -- only add to the original post...

Re: can't import using exporter
by Corion (Patriarch) on Mar 12, 2012 at 21:20 UTC

    Your error is that you try to import a subroutine:

    import Debug qw{Filename2Fields};

    but Debug only exports $Filename2Fields. And you never import that, and that seems to be what Perl complains about.

    You could have put some more work into reducing your test case into a small, self-contained program, which would make it easier for us to reproduce your situation. If indeed 5.14 were broken, it would be rare that you would be the first person to realize that, especially about 1 year after 5.14 was released and shortly before 5.16 gets released.

      I've tried it with and without the sigils in both places -- it made no difference.

      You will note that I have my exports in EXPORT, not EXPORT_OK -- so shouldn't that mean they are all exported by default?

        ... shouldn't that mean they are all exported by default?

        Yes, it does.

        I've tried it with and without the sigils in both places -- it made no difference.

        Like I wrote, the lack of the BEGIN is tripping you too. Either wrap your imports in BEGIN blocks or extract these packages into separate files and use use.


        Improve your skills with Modern Perl: the free book.