Modules ======= Nim supports splitting a program into pieces by a module concept. Each module needs to be in its own file and has its own `namespace`:idx:. Modules enable `information hiding`:idx: and `separate compilation`:idx:. A module may gain access to symbols of another module by the `import`:idx: statement. `Recursive module dependencies`:idx: are allowed, but slightly subtle. Only top-level symbols that are marked with an asterisk (``*``) are exported. A valid module name can only be a valid Nim identifier (and thus its filename is ``identifier.nim``). The algorithm for compiling modules is: - compile the whole module as usual, following import statements recursively - if there is a cycle only import the already parsed symbols (that are exported); if an unknown identifier occurs then abort This is best illustrated by an example: .. code-block:: nim # Module A type T1* = int # Module A exports the type ``T1`` import B # the compiler starts parsing B proc main() = var i = p(3) # works because B has been parsed completely here main() .. code-block:: nim # Module B import A # A is not parsed here! Only the already known symbols # of A are imported. proc p*(x: A.T1): A.T1 = # this works because the compiler has already # added T1 to A's interface symbol table result = x + 1 Import statement ~~~~~~~~~~~~~~~~ After the ``import`` statement a list of module names can follow or a single module name followed by an ``except`` list to prevent some symbols to be imported: .. code-block:: nim import strutils except `%`, toUpper # doesn't work then: echo "$1" % "abc".toUpper It is not checked that the ``except`` list is really exported from the module. This feature allows to compile against an older version of the module that does not export these identifiers. Include statement ~~~~~~~~~~~~~~~~~ The ``include`` statement does something fundamentally different than importing a module: it merely includes the contents of a file. The ``include`` statement is useful to split up a large module into several files: .. code-block:: nim include fileA, fileB, fileC Module names in imports ~~~~~~~~~~~~~~~~~~~~~~~ A module alias can be introduced via the ``as`` keyword: .. code-block:: nim import strutils as su, sequtils as qu echo su.format("$1", "lalelu") The original module name is then not accessible. The notations ``path/to/module`` or ``path.to.module`` or ``"path/to/module"`` can be used to refer to a module in subdirectories: .. code-block:: nim import lib.pure.strutils, lib/pure/os, "lib/pure/times" Note that the module name is still ``strutils`` and not ``lib.pure.strutils`` and so one **cannot** do: .. code-block:: nim import lib.pure.strutils echo lib.pure.strutils Likewise the following does not make sense as the name is ``strutils`` already: .. code-block:: nim import lib.pure.strutils as strutils From import statement ~~~~~~~~~~~~~~~~~~~~~ After the ``from`` statement a module name follows followed by an ``import`` to list the symbols one likes to use without explict full qualification: .. code-block:: nim from strutils import `%` echo "$1" % "abc" # always possible: full qualification: echo strutils.replace("abc", "a", "z") It's also possible to use ``from module import nil`` if one wants to import the module but wants to enforce fully qualified access to every symbol in ``module``. Export statement ~~~~~~~~~~~~~~~~ An ``export`` statement can be used for symbol fowarding so that client modules don't need to import a module's dependencies: .. code-block:: nim # module B type MyObject* = object .. code-block:: nim # module A import B export B.MyObject proc `$`*(x: MyObject): string = "my object" .. code-block:: nim # module C import A # B.MyObject has been imported implicitly here: var x: MyObject echo $x Note on paths ----------- In module related statements, if any part of the module name / path begins with a number, you may have to quote it in double quotes. In the following example, it would be seen as a literal number '3.0' of type 'float64' if not quoted, if uncertain - quote it: .. code-block:: nim import "gfx/3d/somemodule" Scope rules ----------- Identifiers are valid from the point of their declaration until the end of the block in which the declaration occurred. The range where the identifier is known is the scope of the identifier. The exact scope of an identifier depends on the way it was declared. Block scope ~~~~~~~~~~~ The *scope* of a variable declared in the declaration part of a block is valid from the point of declaration until the end of the block. If a block contains a second block, in which the identifier is redeclared, then inside this block, the second declaration will be valid. Upon leaving the inner block, the first declaration is valid again. An identifier cannot be redefined in the same block, except if valid for procedure or iterator overloading purposes. Tuple or object scope ~~~~~~~~~~~~~~~~~~~~~ The field identifiers inside a tuple or object definition are valid in the following places: * To the end of the tuple/object definition. * Field designators of a variable of the given tuple/object type. * In all descendant types of the object type. Module scope ~~~~~~~~~~~~ All identifiers of a module are valid from the point of declaration until the end of the module. Identifiers from indirectly dependent modules are *not* available. The `system`:idx: module is automatically imported in every module. If a module imports an identifier by two different modules, each occurrence of the identifier has to be qualified, unless it is an overloaded procedure or iterator in which case the overloading resolution takes place: .. code-block:: nim # Module A var x*: string .. code-block:: nim # Module B var x*: int .. code-block:: nim # Module C import A, B write(stdout, x) # error: x is ambiguous write(stdout, A.x) # no error: qualifier used var x = 4 write(stdout, x) # not ambiguous: uses the module C's x