123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- 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
|