diff options
Diffstat (limited to 'doc/tut1.rst')
-rw-r--r-- | doc/tut1.rst | 123 |
1 files changed, 74 insertions, 49 deletions
diff --git a/doc/tut1.rst b/doc/tut1.rst index be5cd8c11..9e6f1ab3c 100644 --- a/doc/tut1.rst +++ b/doc/tut1.rst @@ -30,6 +30,7 @@ The first program We start the tour with a modified "hello world" program: .. code-block:: Nim + :test: "nim c $1" # This is a comment echo "What's your name? " var name: string = readLine(stdin) @@ -72,6 +73,7 @@ you can leave out the type in the declaration (this is called `local type inference`:idx:). So this will work too: .. code-block:: Nim + :test: "nim c $1" var name = readLine(stdin) Note that this is basically the only form of type inference that exists in @@ -116,6 +118,7 @@ Comments start anywhere outside a string or character literal with the hash character ``#``. Documentation comments start with ``##``: .. code-block:: nim + :test: "nim c $1" # A comment. var myVariable: int ## a documentation comment @@ -129,6 +132,7 @@ Multiline comments are started with ``#[`` and terminated with ``]#``. Multilin comments can also be nested. .. code-block:: nim + :test: "nim c $1" #[ You can have any Nim code text commented out inside this with no indentation restrictions. @@ -142,6 +146,7 @@ You can also use the `discard statement <#procedures-discard-statement>`_ togeth literals* to create block comments: .. code-block:: nim + :test: "nim c $1" discard """ You can have any Nim code text commented out inside this with no indentation restrictions. yes("May I ask a pointless question?") """ @@ -169,6 +174,7 @@ Indentation can be used after the ``var`` keyword to list a whole section of variables: .. code-block:: + :test: "nim c $1" var x, y: int # a comment can occur here too @@ -186,10 +192,11 @@ to a storage location: x = "xyz" # assigns a new value to `x` ``=`` is the *assignment operator*. The assignment operator can be -overloaded. You can declare multiple variables with a single assignment +overloaded. You can declare multiple variables with a single assignment statement and all the variables will have the same value: .. code-block:: + :test: "nim c $1" var x, y = 3 # assigns 3 to the variables `x` and `y` echo "x ", x # outputs "x 3" echo "y ", y # outputs "y 3" @@ -212,12 +219,14 @@ cannot change. The compiler must be able to evaluate the expression in a constant declaration at compile time: .. code-block:: nim + :test: "nim c $1" const x = "abc" # the constant x contains the string "abc" Indentation can be used after the ``const`` keyword to list a whole section of constants: .. code-block:: + :test: "nim c $1" const x = 1 # a comment can occur here too @@ -243,6 +252,7 @@ and put it into a data section": const input = readLine(stdin) # Error: constant expression expected .. code-block:: + :test: "nim c $1" let input = readLine(stdin) # works @@ -260,6 +270,7 @@ If statement The if statement is one way to branch the control flow: .. code-block:: nim + :test: "nim c $1" let name = readLine(stdin) if name == "": echo "Poor soul, you lost your name?" @@ -281,6 +292,7 @@ Another way to branch is provided by the case statement. A case statement is a multi-branch: .. code-block:: nim + :test: "nim c $1" let name = readLine(stdin) case name of "": @@ -338,6 +350,7 @@ While statement The while statement is a simple looping construct: .. code-block:: nim + :test: "nim c $1" echo "What's your name? " var name = readLine(stdin) @@ -358,6 +371,7 @@ provides. The example uses the built-in `countup <system.html#countup>`_ iterator: .. code-block:: nim + :test: "nim c $1" echo "Counting to ten: " for i in countup(1, 10): echo i @@ -409,6 +423,7 @@ Other useful iterators for collections (like arrays and sequences) are * ``pairs`` and ``mpairs`` which provides the element and an index number (immutable and mutable respectively) .. code-block:: nim + :test: "nim c $1" for index, item in ["a","b"].pairs: echo item, " at index ", index # => a at index 0 @@ -421,6 +436,8 @@ new scope. This means that in the following example, ``x`` is not accessible outside the loop: .. code-block:: nim + :test: "nim c $1" + :status: 1 while false: var x = "hi" echo x # does not work @@ -430,6 +447,8 @@ are only visible within the block they have been declared. The ``block`` statement can be used to open a new block explicitly: .. code-block:: nim + :test: "nim c $1" + :status: 1 block myblock: var x = "hi" echo x # does not work either @@ -444,6 +463,7 @@ can leave a ``while``, ``for``, or a ``block`` statement. It leaves the innermost construct, unless a label of a block is given: .. code-block:: nim + :test: "nim c $1" block myblock: echo "entering block" while true: @@ -465,6 +485,7 @@ Like in many other programming languages, a ``continue`` statement starts the next iteration immediately: .. code-block:: nim + :test: "nim c $1" while true: let x = readLine(stdin) if x == "": continue @@ -477,6 +498,7 @@ When statement Example: .. code-block:: nim + :test: "nim c $1" when system.hostOS == "windows": echo "running on Windows!" @@ -549,6 +571,7 @@ an expression is allowed: .. code-block:: nim # computes fac(4) at compile time: + :test: "nim c $1" const fac4 = (var x = 1; for i in 1..4: x *= i; x) @@ -561,6 +584,7 @@ is needed. (Some languages call them *methods* or *functions*.) In Nim new procedures are defined with the ``proc`` keyword: .. code-block:: nim + :test: "nim c $1" proc yes(question: string): bool = echo question, " (y/n)" while true: @@ -597,6 +621,7 @@ automatically at the end of a procedure if there is no ``return`` statement at the exit. .. code-block:: nim + :test: "nim c $1" proc sumTillNegative(x: varargs[int]): int = for i in x: if i < 0: @@ -624,6 +649,7 @@ to be declared with ``var`` in the procedure body. Shadowing the parameter name is possible, and actually an idiom: .. code-block:: nim + :test: "nim c $1" proc printSeq(s: seq, nprinted: int = -1) = var nprinted = if nprinted == -1: s.len else: min(nprinted, s.len) for i in 0 .. <nprinted: @@ -633,6 +659,7 @@ If the procedure needs to modify the argument for the caller, a ``var`` parameter can be used: .. code-block:: nim + :test: "nim c $1" proc divmod(a, b: int; res, remainder: var int) = res = a div b # integer division remainder = a mod b # integer modulo operation @@ -663,6 +690,7 @@ The return value can be ignored implicitly if the called proc/iterator has been declared with the ``discardable`` pragma: .. code-block:: nim + :test: "nim c $1" proc p(x, y: int): int {.discardable.} = return x + y @@ -772,6 +800,7 @@ The "``" notation can also be used to call an operator just like any other procedure: .. code-block:: nim + :test: "nim c $1" if `==`( `+`(3, 4), 7): echo "True" @@ -819,6 +848,7 @@ Iterators Let's return to the simple counting example: .. code-block:: nim + :test: "nim c $1" echo "Counting to ten: " for i in countup(1, 10): echo i @@ -840,6 +870,7 @@ the only thing left to do is to replace the ``proc`` keyword by ``iterator`` and here it is - our first iterator: .. code-block:: nim + :test: "nim c $1" iterator countup(a, b: int): int = var res = a while res <= b: @@ -894,7 +925,8 @@ evaluation. For example: Characters ---------- The `character type` is called ``char``. Its size is always one byte, so -it cannot represent most UTF-8 characters; but it *can* represent one of the bytes that makes up a multi-byte UTF-8 character. +it cannot represent most UTF-8 characters; but it *can* represent one of the bytes +that makes up a multi-byte UTF-8 character. The reason for this is efficiency: for the overwhelming majority of use-cases, the resulting programs will still handle UTF-8 properly as UTF-8 was specially designed for this. @@ -945,6 +977,7 @@ to specify a non-default integer type: .. code-block:: nim + :test: "nim c $1" let x = 0 # x is of type ``int`` y = 0'i8 # y is of type ``int8`` @@ -981,6 +1014,7 @@ Float literals can have a *type suffix* to specify a non-default float type: .. code-block:: nim + :test: "nim c $1" var x = 0.0 # x is of type ``float`` y = 0.0'f32 # y is of type ``float32`` @@ -1002,6 +1036,7 @@ Conversion between basic types is performed by using the type as a function: .. code-block:: nim + :test: "nim c $1" var x: int32 = 1.int32 # same as calling int32(1) y: int8 = int8('a') # 'a' == 97'i8 @@ -1023,6 +1058,7 @@ graphs with cycles. The following example shows that even for basic types there is a difference between the ``$`` and ``repr`` outputs: .. code-block:: nim + :test: "nim c $1" var myBool = true myCharacter = 'n' @@ -1047,6 +1083,7 @@ Advanced types In Nim new types can be defined within a ``type`` statement: .. code-block:: nim + :test: "nim c $1" type biggestInt = int64 # biggest integer type that is available biggestFloat = float64 # biggest float type that is available @@ -1063,6 +1100,7 @@ to an integer value internally. The first symbol is represented at runtime by 0, the second by 1 and so on. For example: .. code-block:: nim + :test: "nim c $1" type Direction = enum @@ -1087,6 +1125,7 @@ explicitly given is assigned the value of the previous symbol + 1. An explicit ordered enum can have *holes*: .. code-block:: nim + :test: "nim c $1" type MyEnum = enum a = 2, b = 4, c = 89 @@ -1125,6 +1164,7 @@ A subrange type is a range of values from an integer or enumeration type (the base type). Example: .. code-block:: nim + :test: "nim c $1" type MySubrange = range[0..5] @@ -1155,6 +1195,7 @@ an array has the same type. The array's index type can be any ordinal type. Arrays can be constructed using ``[]``: .. code-block:: nim + :test: "nim c $1" type IntArray = array[0..5, int] # an array that is indexed with 0..5 @@ -1177,6 +1218,7 @@ length. `low(a) <system.html#low>`_ returns the lowest valid index for the array `a` and `high(a) <system.html#high>`_ the highest valid index. .. code-block:: nim + :test: "nim c $1" type Direction = enum north, east, south, west @@ -1228,6 +1270,7 @@ It is quite common to have arrays start at zero, so there's a shortcut syntax to specify a range from zero to the specified index minus one: .. code-block:: nim + :test: "nim c $1" type IntArray = array[0..5, int] # an array that is indexed with 0..5 QuickArray = array[6, int] # an array that is indexed with 0..5 @@ -1260,6 +1303,7 @@ A sequence may be passed to an openarray parameter. Example: .. code-block:: nim + :test: "nim c $1" var x: seq[int] # a reference to a sequence of integers @@ -1282,6 +1326,7 @@ value. Here the ``for`` statement is looping over the results from the <system.html>`_ module. Examples: .. code-block:: nim + :test: "nim c $1" for value in @[3, 4, 5]: echo value # --> 3 @@ -1308,6 +1353,7 @@ with a compatible base type can be passed to an openarray parameter, the index type does not matter. .. code-block:: nim + :test: "nim c $1" var fruits: seq[string] # reference to a sequence of strings that is initialized with 'nil' capitals: array[3, string] # array of strings with a fixed size @@ -1337,6 +1383,7 @@ arguments to a procedure. The compiler converts the list of arguments to an array automatically: .. code-block:: nim + :test: "nim c $1" proc myWriteln(f: File, a: varargs[string]) = for s in items(a): write(f, s) @@ -1351,6 +1398,7 @@ last parameter in the procedure header. It is also possible to perform type conversions in this context: .. code-block:: nim + :test: "nim c $1" proc myWriteln(f: File, a: varargs[string, `$`]) = for s in items(a): write(f, s) @@ -1374,6 +1422,7 @@ context. A slice is just an object of type Slice which contains two bounds, define operators which accept Slice objects to define ranges. .. code-block:: nim + :test: "nim c $1" var a = "Nim is a progamming language" @@ -1388,27 +1437,31 @@ slice's bounds can hold any value supported by their type, but it is the proc using the slice object which defines what values are accepted. - To understand some of the different ways of specifying the indices of strings, arrays, sequences, etc., - it must be remembered that Nim uses zero-based indices. +To understand some of the different ways of specifying the indices of +strings, arrays, sequences, etc., it must be remembered that Nim uses +zero-based indices. - So the string ``b`` is of length 19, and two different ways of specifying the indices are +So the string ``b`` is of length 19, and two different ways of specifying the +indices are - .. code-block:: nim +.. code-block:: nim "Slices are useless." | | | 0 11 17 using indices ^19 ^8 ^2 using ^ syntax - where ``b[0..^1]`` is equivalent to ``b[0..b.len-1]`` and ``b[0..<b.len]``, and it can be seen that the ``^1`` provides a short-hand way of specifying the ``b.len-1`` +where ``b[0..^1]`` is equivalent to ``b[0..b.len-1]`` and ``b[0..<b.len]``, and it +can be seen that the ``^1`` provides a short-hand way of specifying the ``b.len-1``. - In the above example, because the string ends in a period, to get the portion of the string that is "useless" and replace it with "useful" +In the above example, because the string ends in a period, to get the portion of the +string that is "useless" and replace it with "useful". - ``b[11..^2]`` is the portion "useless", and - ``b[11..^2] = "useful"`` replaces the "useless" portion with "useful", - giving the result "Slices are useful." +``b[11..^2]`` is the portion "useless", and ``b[11..^2] = "useful"`` replaces the +"useless" portion with "useful", giving the result "Slices are useful." - Note: alternate ways of writing this are ``b[^8..^2] = "useful"`` or as ``b[11..b.len-2] = "useful"`` or as ``b[11..<b.len-1] = "useful"`` or as .... +Note: alternate ways of writing this are ``b[^8..^2] = "useful"`` or +as ``b[11..b.len-2] = "useful"`` or as ``b[11..<b.len-1] = "useful"``. Tuples ------ @@ -1425,6 +1478,7 @@ The assignment operator for tuples copies each component. The notation integer. .. code-block:: nim + :test: "nim c $1" type Person = tuple[name: string, age: int] # type representing a person: @@ -1470,6 +1524,7 @@ otherwise you will be assigning the same value to all the individual variables! For example: .. code-block:: nim + :test: "nim c $1" import os @@ -1509,10 +1564,10 @@ tuple/object field operator) and ``[]`` (array/string/sequence index operator) operators perform implicit dereferencing operations for reference types: .. code-block:: nim + :test: "nim c $1" type - Node = ref NodeObj - NodeObj = object + Node = ref object le, ri: Node data: int var @@ -1539,6 +1594,7 @@ techniques. Example: .. code-block:: nim + :test: "nim c $1" proc echoItem(x: int) = echo x proc forEach(action: proc (x: int)) = @@ -1556,9 +1612,11 @@ listed in the `manual <manual.html#types-procedural-type>`_. Distinct type ------------- -A Distinct type allows for the creation of new type that "does not imply a subtype relationship between it and its base type". +A Distinct type allows for the creation of new type that "does not imply a +subtype relationship between it and its base type". You must **explicitly** define all behaviour for the distinct type. -To help with this, both the distinct type and its base type can cast from one type to the other. +To help with this, both the distinct type and its base type can cast from one +type to the other. Examples are provided in the `manual <manual.html#types-distinct-type>`_. Modules @@ -1593,39 +1651,6 @@ Each module has a special magic constant ``isMainModule`` that is true if the module is compiled as the main file. This is very useful to embed tests within the module as shown by the above example. -Modules that depend on each other are possible, but strongly discouraged, -because then one module cannot be reused without the other. - -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 - - A symbol of a module *can* be *qualified* with the ``module.symbol`` syntax. And if a symbol is ambiguous, it *must* be qualified. A symbol is ambiguous if it is defined in two (or more) different modules and both modules are |