syntax require

Documentation for syntax require assembled from the following types:

language documentation Modules

From Modules

(Modules) require

require loads a compunit and imports definite symbols at runtime.

say "loading MyModule";
require MyModule;

The compunit name can be in a runtime variable if you put it inside an indirect lookup.

my $name = 'MyModule';
require ::($name);

The symbols provided by the loaded module will not be imported into the current scope. You may use dynamic lookup or dynamic subsets to use them by providing the fully qualified name of a symbol, for instance:

require ::("Test");
my &mmk = ::("Test::EXPORT::DEFAULT::&ok");
mmk('oi‽'); # OUTPUT: «ok 1 - ␤»

The FQN of ok is Test::EXPORT::DEFAULT::&ok. We are aliasing it to mmk so that we can use that symbol provided by Test in the current scope.

To import symbols you must define them at compile time. NOTE: require is lexically scoped:

sub do-something {
   require MyModule <&something>;
   say ::('MyModule'); # MyModule symbol exists here 
   something() # &something will be defined here 
}
say ::('MyModule'); # This will NOT contain the MyModule symbol 
do-something();
# &something will not be defined here

If MyModule doesn't export &something then require will fail.

A require with compile-time symbol will install a placeholder package that will be updated to the loaded module, class, or package. Note that the placeholder will be kept, even if require failed to load the module. This means that checking if a module loaded like this is wrong:

# *** WRONG: *** 
try require Foo;
if ::('Foo'~~ Failure { say "Failed to load Foo!"}
# *** WRONG: ***

As the compile-time installed package causes ::('Foo') to never be a Failure. The correct way is:

# Use return value to test whether loading succeeded: 
(try require Foo=== Nil and say "Failed to load Foo!";
 
# Or use a runtime symbol lookup with require, to avoid compile-time 
# package installation: 
try require ::('Foo');
if ::('Foo'~~ Failure {
    say "Failed to load Foo!";
}

In the current (6.d) version of the language, required symbols are no longer transitively exposed, which means that you need to import symbols from the module they were originally declared, not from the module where they have been imported.