http://qs1969.pair.com?node_id=637337


in reply to Re: require mystery
in thread require mystery

I followed your hunch to look deeper, as it seemed line 2 should have failed for me, even if there had been a prior use.

my $pathtool = "File::Path";
eval {require $pathtool}; # FAILS
if ($@) {print $@;} # "No File::Path in @INC"

eval "require $pathtool"; # OK
eval {require File::Path}; # OK
eval {$pathtool->import("mkpath")}; # OK

Clearly $pathtool wont work in the FIRST block eval where the bareword will, but will work in the SECOND block eval. A subtle trap for young players! But I am relieved. Thanks for your help.

Pstack

Replies are listed 'Best First'.
Re^3: require mystery
by Corion (Patriarch) on Sep 06, 2007 at 07:38 UTC

    No:

    require $pathtool;

    is exactly the same as

    require "File::Path";

    which fails. Your other attempt,

    eval "require $pathtool";

    evaluates the string, which then looks like

    require File::Path;

    which succeeds. Consider using the following code if you want a dynamic module loader:

    sub require_package { for (@_) { (my $file = $_) =~ s-::|'-/-g; require "$file.pm"; }; };

    Other alternatives which I recommend against are UNIVERSAL::require and Module::Load because they both hide fatal errors from you, for example compilation errors in the required modules.

    Maybe you might want Module::Pluggable for a plugin system.

      Yes, I see, and like your custom function. The code had been working previously with an expression eval before I altered it to the FIRST block eval.

      Did you notice how I was thrown off by the success nearby of the SECOND block eval which survived all versions:

      eval {$pathtool->import("mkpath")}; #OK

      which would not then seem right either if similarly translated as ..(though it may be right?)..:

      "File::Path"->import("mkpath");#??

      Mmm!

      cheers

      Pstack

        Perl allows barewords or strings (which are basically the same, except that a bareword comes without quotes, hence, "bare") as invocants:

        File::Path->import(...)

        is the same as:

        "File::Path"->import(...)

        and

        my $pathtool = "File::Path"; $pathtool->import(...)

        and all three translate to:

        File::Path::import("File::Path",...);