mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-14 15:23:27 +00:00
test the snippets in tut2.rst
This commit is contained in:
52
doc/tut2.rst
52
doc/tut2.rst
@@ -55,6 +55,7 @@ Objects have access to their type at runtime. There is an
|
||||
``of`` operator that can be used to check the object's type:
|
||||
|
||||
.. code-block:: nim
|
||||
:test: "nim c $1"
|
||||
type
|
||||
Person = ref object of RootObj
|
||||
name*: string # the * means that `name` is accessible from other modules
|
||||
@@ -103,6 +104,7 @@ would require arbitrary symbol lookahead which slows down compilation.)
|
||||
Example:
|
||||
|
||||
.. code-block:: nim
|
||||
:test: "nim c $1"
|
||||
type
|
||||
Node = ref object # a reference to an object with the following field:
|
||||
le, ri: Node # left and right subtrees
|
||||
@@ -144,6 +146,7 @@ variant types are needed.
|
||||
An example:
|
||||
|
||||
.. code-block:: nim
|
||||
:test: "nim c $1"
|
||||
|
||||
# This is an example how an abstract syntax tree could be modelled in Nim
|
||||
type
|
||||
@@ -201,9 +204,11 @@ This method call syntax is not restricted to objects, it can be used
|
||||
for any type:
|
||||
|
||||
.. code-block:: nim
|
||||
:test: "nim c $1"
|
||||
import strutils
|
||||
|
||||
echo "abc".len # is the same as echo len("abc")
|
||||
echo "abc".toUpper()
|
||||
echo "abc".toUpperAscii()
|
||||
echo({'a', 'b', 'c'}.card)
|
||||
stdout.writeLine("Hallo") # the same as writeLine(stdout, "Hallo")
|
||||
|
||||
@@ -213,6 +218,7 @@ postfix notation.)
|
||||
So "pure object oriented" code is easy to write:
|
||||
|
||||
.. code-block:: nim
|
||||
:test: "nim c $1"
|
||||
import strutils, sequtils
|
||||
|
||||
stdout.writeLine("Give a list of numbers (separated by spaces): ")
|
||||
@@ -228,6 +234,7 @@ the same. But setting a value is different; for this a special setter syntax
|
||||
is needed:
|
||||
|
||||
.. code-block:: nim
|
||||
:test: "nim c $1"
|
||||
|
||||
type
|
||||
Socket* = ref object of RootObj
|
||||
@@ -252,6 +259,7 @@ The ``[]`` array access operator can be overloaded to provide
|
||||
`array properties`:idx:\ :
|
||||
|
||||
.. code-block:: nim
|
||||
:test: "nim c $1"
|
||||
type
|
||||
Vector* = object
|
||||
x, y, z: float
|
||||
@@ -283,23 +291,24 @@ Procedures always use static dispatch. For dynamic dispatch replace the
|
||||
``proc`` keyword by ``method``:
|
||||
|
||||
.. code-block:: nim
|
||||
:test: "nim c $1"
|
||||
type
|
||||
PExpr = ref object of RootObj ## abstract base class for an expression
|
||||
PLiteral = ref object of PExpr
|
||||
Expression = ref object of RootObj ## abstract base class for an expression
|
||||
Literal = ref object of Expression
|
||||
x: int
|
||||
PPlusExpr = ref object of PExpr
|
||||
a, b: PExpr
|
||||
PlusExpr = ref object of Expression
|
||||
a, b: Expression
|
||||
|
||||
# watch out: 'eval' relies on dynamic binding
|
||||
method eval(e: PExpr): int =
|
||||
method eval(e: Expression): int =
|
||||
# override this base method
|
||||
quit "to override!"
|
||||
|
||||
method eval(e: PLiteral): int = e.x
|
||||
method eval(e: PPlusExpr): int = eval(e.a) + eval(e.b)
|
||||
method eval(e: Literal): int = e.x
|
||||
method eval(e: PlusExpr): int = eval(e.a) + eval(e.b)
|
||||
|
||||
proc newLit(x: int): PLiteral = PLiteral(x: x)
|
||||
proc newPlus(a, b: PExpr): PPlusExpr = PPlusExpr(a: a, b: b)
|
||||
proc newLit(x: int): Literal = Literal(x: x)
|
||||
proc newPlus(a, b: Expression): PlusExpr = PlusExpr(a: a, b: b)
|
||||
|
||||
echo eval(newPlus(newPlus(newLit(1), newLit(2)), newLit(4)))
|
||||
|
||||
@@ -311,6 +320,7 @@ In a multi-method all parameters that have an object type are used for the
|
||||
dispatching:
|
||||
|
||||
.. code-block:: nim
|
||||
:test: "nim c $1"
|
||||
|
||||
type
|
||||
Thing = ref object of RootObj
|
||||
@@ -365,6 +375,7 @@ Raise statement
|
||||
Raising an exception is done with the ``raise`` statement:
|
||||
|
||||
.. code-block:: nim
|
||||
:test: "nim c $1"
|
||||
var
|
||||
e: ref OSError
|
||||
new(e)
|
||||
@@ -385,6 +396,9 @@ Try statement
|
||||
The ``try`` statement handles exceptions:
|
||||
|
||||
.. code-block:: nim
|
||||
:test: "nim c $1"
|
||||
from strutils import parseInt
|
||||
|
||||
# read the first two lines of a text file that should contain numbers
|
||||
# and tries to add them
|
||||
var
|
||||
@@ -479,6 +493,7 @@ with `type parameters`:idx:. They are most useful for efficient type safe
|
||||
containers:
|
||||
|
||||
.. code-block:: nim
|
||||
:test: "nim c $1"
|
||||
type
|
||||
BinaryTree*[T] = ref object # BinaryTree is a generic type with
|
||||
# generic param ``T``
|
||||
@@ -573,6 +588,7 @@ Templates are especially useful for lazy evaluation purposes. Consider a
|
||||
simple proc for logging:
|
||||
|
||||
.. code-block:: nim
|
||||
:test: "nim c $1"
|
||||
const
|
||||
debug = true
|
||||
|
||||
@@ -590,6 +606,7 @@ evaluation for procedures is *eager*).
|
||||
Turning the ``log`` proc into a template solves this problem:
|
||||
|
||||
.. code-block:: nim
|
||||
:test: "nim c $1"
|
||||
const
|
||||
debug = true
|
||||
|
||||
@@ -611,6 +628,7 @@ If the template has no explicit return type,
|
||||
To pass a block of statements to a template, use 'untyped' for the last parameter:
|
||||
|
||||
.. code-block:: nim
|
||||
:test: "nim c $1"
|
||||
|
||||
template withFile(f: untyped, filename: string, mode: FileMode,
|
||||
body: untyped): typed =
|
||||
@@ -665,6 +683,7 @@ The following example implements a powerful ``debug`` command that accepts a
|
||||
variable number of arguments:
|
||||
|
||||
.. code-block:: nim
|
||||
:test: "nim c $1"
|
||||
# to work with Nim syntax trees, we need an API that is defined in the
|
||||
# ``macros`` module:
|
||||
import macros
|
||||
@@ -744,6 +763,7 @@ dynamic code into something that compiles statically. For the exercise we will
|
||||
use the following snippet of code as the starting point:
|
||||
|
||||
.. code-block:: nim
|
||||
:test: "nim c $1"
|
||||
|
||||
import strutils, tables
|
||||
|
||||
@@ -863,9 +883,9 @@ variables with ``cfg``. In essence, what the compiler is doing is replacing
|
||||
the line calling the macro with the following snippet of code:
|
||||
|
||||
.. code-block:: nim
|
||||
const cfgversion= "1.1"
|
||||
const cfglicenseOwner= "Hyori Lee"
|
||||
const cfglicenseKey= "M1Tl3PjBWO2CC48m"
|
||||
const cfgversion = "1.1"
|
||||
const cfglicenseOwner = "Hyori Lee"
|
||||
const cfglicenseKey = "M1Tl3PjBWO2CC48m"
|
||||
|
||||
You can verify this yourself adding the line ``echo source`` somewhere at the
|
||||
end of the macro and compiling the program. Another difference is that instead
|
||||
@@ -891,12 +911,13 @@ an expression macro. Since we know that we want to generate a bunch of
|
||||
see what the compiler *expects* from us:
|
||||
|
||||
.. code-block:: nim
|
||||
:test: "nim c $1"
|
||||
import macros
|
||||
|
||||
dumpTree:
|
||||
const cfgversion: string = "1.1"
|
||||
const cfglicenseOwner= "Hyori Lee"
|
||||
const cfglicenseKey= "M1Tl3PjBWO2CC48m"
|
||||
const cfglicenseOwner = "Hyori Lee"
|
||||
const cfglicenseKey = "M1Tl3PjBWO2CC48m"
|
||||
|
||||
During compilation of the source code we should see the following lines in the
|
||||
output (again, since this is a macro, compilation is enough, you don't have to
|
||||
@@ -996,6 +1017,7 @@ Lifting Procs
|
||||
+++++++++++++
|
||||
|
||||
.. code-block:: nim
|
||||
:test: "nim c $1"
|
||||
import math
|
||||
|
||||
template liftScalarProc(fname) =
|
||||
|
||||
Reference in New Issue
Block a user