Upgrade Information for Lexical require

2017-03-18

What's Happening?

Rakudo Compiler release 2017.03 includes the final piece of lexical module loading work: lexical require. This work was first announced in December, in http://rakudo.org/2016/12/17/lexical-module-loading/

There are two changes that may impact your code:

  • require now imports symbols lexically. If you require inside a block, the symbols won't be available outside of it.
  • Compile-time require installs a placeholder package symbol that remains available even if required item was not found.

Upgrade Information

Lexical Symbols

WRONG:

# WRONG:
try { require Foo; 1 } and ::('Foo').new;

The require above is inside a block and so its symbols won't be available outside of it and the look up will fail.

CHANGE TO:

(try require Foo) !=== Nil and ::('Foo').new;

Now the require installs the symbols into scope that's lexically accessible to the ::('Foo') look up.

Optional Loading

WRONG:

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

This construct installs a package named Foo, which would be replaced by the loaded Foo if it were found, but if it weren't, the package will remain a package, not a Failure, and so the above ~~ test will always be False.

CHANGE TO:

# Use return value to test whether loading succeeded:
(try require Foo) === Nil and say "Failed to load Foo!";

# Or use a run-time symbol lookup with require, to avoid compile-time
# package installation:
try require ::('Foo');
if ::('Foo') ~~ Failure {
    say "Failed to load Foo!";
}

In the first example above, we test the return value of try isn't Nil, since on successful loading it will be a Foo module, class, or package.

The second example uses a run-time symbol lookup in require and so it never needs to install the package placeholder during the compile time. Therefore, the ::('Foo') ~~ test does work as intended.

Help and More Info

If you require help or more information, please join our chat channel #perl6 on irc.freenode.net