Unable to load `Cwd` (and other, non-core modules) at run time

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

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

but this is not so, for Bareword "getcwd" not allowed ...

Cwd exports getcwd by default. I tried to name the function import , and I tried to use its other functions. It works with the full name say Cwd::getcwd , so I think it does not import.

This works as an attempt for several other core modules I tried, for example

 use warnings; use strict; eval { require List::Util; List::Util->import('max'); }; if ( $@ ) { die "Can't load List::Util: $@ " } my $max = max (1, 14, 3, 26, 2); print "Max is $max\n"; 

NOTE added . Apparently, function calls with parentheses give the key to the compiler. However, in my opinion, the question remains, see EDIT at the end. In addition, a function like the first BLOCK LIST from the above module does not work.


However, it does not work for several (well installed) non-core modules that I tried. Worse and more vaguely, it does not work even with fully qualified names.

I can imagine that the character (function) used is not known at compile time if require used at run time, but it works for (other) base modules. I thought this was the standard way to load at runtime.

If I need to use full names for dynamic loading, then fine, but what is it with inconsistency? And how can I load (and use) non-core modules at runtime?

I also tried with Module::Load::Conditional , and this did not work.

What am I missing and how to load modules at runtime? (Tried 5.16 and 5.10.1 .)


EDIT

As noted by Matt Jacob , calling with brackets works getcwd() . However, considering perlsub

NAME LIST; # Brackets are optional if specified / imported.

this means that the import did not work, and the question of why remains.

Also, using a variety of syntax based on how the module loads is not very good. Also, I cannot get non-core modules to work this way, especially those that have syntax like List :: MoreUtils .

+5
source share
1 answer

Firstly, it has nothing to do with the core or non-core modules. This happens when the analyzer must guess if 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 hint to indicate that it is a function ( getcwd() or &getcwd ), the parser does not 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 in the symbol table main:: no max . However, since you call max with parentheses, the parser may guess that it is a function that will be defined later, so strict does not complain.

In both cases, strict checking occurs before import ever called.


List :: MoreUtils is special because functions use prototypes. Prototypes are ignored if the function definition is not displayed at compile time. Thus, you should not only give the parser a hint that you are calling the function, you should also call it differently, as 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 ); 
+4
source

Source: https://habr.com/ru/post/1261121/


All Articles