Creating module packages for code reuse
N.B. "Module" is an overloaded term in Raku; this document focuses on use of the module
declarator.
Modules, like classes and grammars, are a kind of package. Module objects are instances of the ModuleHOW
metaclass; this provides certain capabilities useful for creating namespaces, versioning, delegation and data encapsulation (see also class and role).
To create a module, use the module
declarator:
say M.HOW; # OUTPUT: «Perl6::Metamodel::ModuleHOW.new»
Here we define a new module named M
; introspection with HOW
confirms that the metaclass underlying M
is Perl6::Metamodel::ModuleHOW
.
Modules are primarily useful for encapsulating code and data that do not belong inside a class or role definition. Module contents (classes, subroutines, variables, etc.) can be exported from a module with the is export
trait; these are available in the caller's namespace once the module has been imported with import
or use
. A module can also selectively expose symbols within its namespace for qualified reference via our
.
To illustrate module scoping and export rules, let's begin by defining a simple module M
:
Recall that subroutines are lexically scoped unless otherwise specified (declarator sub
is equivalent to my sub
), so greeting
in the above example is lexically scoped to the module and inaccessible outside of it. We've also defined loud-greeting
with the our
declarator, which means that in addition to being lexically scoped it is aliased in the module's symbol table. Finally, friendly-greeting
is marked for export; it will be registered in the caller's symbol table when the module is imported:
import M; # import the modulesay M::loud-greeting; # OUTPUT: «GREETINGS, CAMELIA!»say friendly-greeting; # OUTPUT: «Greetings, friend!»
While .raku
and .rakumod
files are sometimes referred to as "modules", they are really just normal files that are loaded and compiled when you write need
, use
or require
.
For a .rakumod
file to provide a module in the sense that we've been using, it needs to declare one with module
as documented above. For example, by placing module M
inside Foo.rakumod
, we can load and use the module as follows:
use Foo; # find Foo.rakumod, run need followed by importsay M::loud-greeting; # OUTPUT: «GREETINGS, CAMELIA!»say friendly-greeting; # OUTPUT: «Greetings, friend!»
Note the decoupling between file and module names—a .rakumod
file can declare zero or more modules with arbitrary identifiers.
Often we want a .rakumod
file to provide a single module and nothing more. Here a common convention is for the file basename to match the module name. Returning to Foo.rakumod
, it is apparent that it only provides a single module, M
; in this case, we might want to rename M
to Foo
. The amended file would then read:
which can be used more consistently by the caller (note the relationship between the use Foo
and Foo::
):
use Foo;say Foo::loud-greeting; # OUTPUT: «GREETINGS, CAMELIA!»say friendly-greeting; # OUTPUT: «Greetings, friend!»
If Foo.rakumod
is placed deeper within the source tree, e.g. at lib/Utils/Foo.rakumod
, we can elect to name the module Utils::Foo
to maintain consistency.
unit
keywordFiles that only provide a single module can be written more concisely with the unit
keyword; unit module
specifies that the rest of the compilation unit is part of the declared module. Here's Foo.rakumod
rewritten with unit
:
unit ;sub greeting ( = 'Camelia')our sub loud-greeting (--> Str)sub friendly-greeting is export
Everything following the unit declaration is part of the Foo
module specification.
(Note that unit
can also be used with class
, grammar
and role
.)
module
?To better understand what the module
declarator is doing in Foo.rakumod
, let's contrast it with a variant file, Bar.rakumod
, that omits the declaration. The subroutine definitions below are almost identical (the only difference is in the body of greeting
, modified for clarity):
sub greeting ( = 'Camelia')our sub loud-greeting (--> Str)sub friendly-greeting is export
As a reminder, here's how we used Foo.rakumod
before,
use Foo;say Foo::loud-greeting; # OUTPUT: «GREETINGS, CAMELIA!»say friendly-greeting; # OUTPUT: «Greetings, friend!»
and here's how we use Bar.rakumod
,
use Bar;say loud-greeting; # OUTPUT: «GREETINGS FROM BAR, CAMELIA!»say friendly-greeting; # OUTPUT: «Greetings from Bar, friend!»
Note the use of loud-greeting
rather than Bar::loud-greeting
as Bar
is not a known symbol (we didn't create a module
of that name in Bar.rakumod
). But why is loud-greeting
callable even though we didn't mark it for export? The answer is simply that Bar.rakumod
doesn't create a new package namespace—$?PACKAGE
is still set to GLOBAL
—so when we declare loud-greeting
as our
, it is registered in the GLOBAL
symbol table.
Thankfully, Raku protects us from accidentally clobbering call site definitions (e.g. builtins). Consider the following addition to Bar.rakumod
:
our sub say ()
This creates a lexical alias, hiding the say
builtin inside Bar.rakumod
but leaving the caller's say
unchanged. Consequently, the following call to say
still works as expected:
use Bar;say 'Carry on, carry on...'; # OUTPUT: «Carry on, carry on...»