Skip to content

Instantly share code, notes, and snippets.

@niner
Last active May 30, 2018 07:10
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save niner/70f7b46eefb7e22af78d896bea11efeb to your computer and use it in GitHub Desktop.
Save niner/70f7b46eefb7e22af78d896bea11efeb to your computer and use it in GitHub Desktop.

Perl 6 takes great care to avoid global state, i.e. whatever you do in your module, it should not affect other code. That's why e.g. subroutine definitions are lexically (my) scoped by default. If you want others to see them, you need to explicitly make them our scoped or export them.

Classes are exported by default on the assumption that loading a module will not be of much use when you cannot access the classes it contains. This works as advertised with a small but important caveat. Those classes are not only visible in the computation unit that loads the module, but globally. This means that as soon as some code loads a module, those classes are immediately visible everywhere.

For example, given a module Foo:

unit class Foo;
use Bar;

And your own program:

use Foo;
my $foo = Foo.new; # works as expected
my $bar = Bar.new; # huh!? Where is Bar coming from?

This doesn't sound so bad (it at least saves you some typing), except for that it makes another feature of Perl 6 impossible to have: the ability to load multiple versions of a module at the same time in different parts of your program:

{
    use Baz:ver(v1);
    my $old-baz = Baz.new;
}
{
    use Baz:ver(v2);
    my $shiny-new-baz = Baz.new;
}

This will explode as on loading Baz:ver(v2), rakudo will complain about "Baz" already being defined.

To fix this, we no longer register loaded classes globally but only in the scope which loaded them in the first place. Coming back to our first example, we would need to explicitly load Bar in the main program:

use Foo;
use Bar;
my $foo = Foo.new; # still works of course
my $bar = Bar.new; # now it's clear where Bar is coming from

So if you suddenly get an "Undeclared name: Bar" error message after upgrading to a newer Perl 6 compiler, you will most probably just need to add a: "use Bar;" to your code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment