Cannot load `Cwd` (and other, non-core, modules) at runtime

后端 未结 1 765
感动是毒
感动是毒 2021-01-18 02:33

Imagine I want to load a module at runtime. I expected this to work

use warnings;
use strict;

eval {
    require Cwd; 
    Cwd->import;
};
if ($@) { die          


        
1条回答
  •  小鲜肉
    小鲜肉 (楼主)
    2021-01-18 02:45

    First, this has nothing to do with core vs. non-core modules. It happens when the parser has to guess whether a particular token is a function call.


    eval {
        require Cwd; 
        Cwd->import;
    };
    if ($@) { die "Can't load Cwd: $@" }
    
    say "Dir: ", getcwd;
    

    At compile time, there is no getcwd in the main:: symbol table. Without any hints to indicate that it's a function (getcwd() or &getcwd), the parser has no way to know, and strict complains.


    eval { 
        require List::Util; 
        List::Util->import('max');
    };
    if ($@) { die "Can't load List::Util: $@" }
    
    my $max = max (1, 14, 3, 26, 2);
    

    At compile time, there is no max in the main:: symbol table. However, since you call max with parentheses, the parser can guess that it's a function that will be defined later, so strict doesn't complain.

    In both cases, the strict check happens before import is ever called.


    List::MoreUtils is special because the functions use prototypes. Prototypes are ignored if the function definition is not visible at compile time. So, not only do you have to give the parser a hint that you're calling a function, you also have to call it differently since the prototype will be ignored:

    use strict;
    use warnings 'all';
    use 5.010;
    
    eval {
        require List::MoreUtils;
        List::MoreUtils->import('any')
    };
    die "Can't load List::MoreUtils: $@" if $@;
    
    say 'found' if any( sub { $_ > 5 }, 1..9 );
    

    0 讨论(0)
提交回复
热议问题