diff options
author | Andreas Rumpf <andreas@andreas-desktop> | 2009-11-15 17:46:15 +0100 |
---|---|---|
committer | Andreas Rumpf <andreas@andreas-desktop> | 2009-11-15 17:46:15 +0100 |
commit | 281609c358b139d55461af842ce29f39f01b2441 (patch) | |
tree | a811f925fc263b0a9c2c021337b3350f096f6953 /doc/tut2.txt | |
parent | 63e9a88c1f1077b4e7f826324ab772f3c88450b2 (diff) | |
download | Nim-281609c358b139d55461af842ce29f39f01b2441.tar.gz |
fixed typos in documentation
Diffstat (limited to 'doc/tut2.txt')
-rwxr-xr-x | doc/tut2.txt | 158 |
1 files changed, 79 insertions, 79 deletions
diff --git a/doc/tut2.txt b/doc/tut2.txt index c81f98e77..a139fb5de 100755 --- a/doc/tut2.txt +++ b/doc/tut2.txt @@ -11,9 +11,9 @@ Nimrod Tutorial (Part II) Introduction ============ - "With great power comes great responsibility." -- Spider-man + "With great power comes great responsibility." -- Spiderman -This document is a tutorial for the advanced constructs of the *Nimrod* +This document is a tutorial for the advanced constructs of the *Nimrod* programming language. @@ -23,17 +23,17 @@ Pragmas are Nimrod's method to give the compiler additional information/ commands without introducing a massive number of new keywords. Pragmas are processed during semantic checking. Pragmas are enclosed in the special ``{.`` and ``.}`` curly dot brackets. This tutorial does not cover -pragmas. See the `manual <manual.html>`_ or `user guide <nimrodc.html>`_ for +pragmas. See the `manual <manual.html>`_ or `user guide <nimrodc.html>`_ for a description of the available pragmas. Object Oriented Programming =========================== -While Nimrod's support for object oriented programming (OOP) is minimalistic, -powerful OOP technics can be used. OOP is seen as *one* way to design a +While Nimrod's support for object oriented programming (OOP) is minimalistic, +powerful OOP technics can be used. OOP is seen as *one* way to design a program, not *the only* way. Often a procedural approach leads to simpler -and more efficient code. In particular, prefering aggregation over inheritance +and more efficient code. In particular, prefering composition over inheritance is often the better design. @@ -84,8 +84,8 @@ Mutually recursive types ------------------------ Objects, tuples and references can model quite complex data structures which -depend on each other; they are *mutually recursive*. In Nimrod -these types can only be declared within a single type section. (Anything else +depend on each other; they are *mutually recursive*. In Nimrod +these types can only be declared within a single type section. (Anything else would require arbitrary symbol lookahead which slows down compilation.) Example: @@ -106,22 +106,22 @@ Example: Type conversions ---------------- Nimrod distinguishes between `type casts`:idx: and `type conversions`:idx:. -Casts are done with the ``cast`` operator and force the compiler to -interpret a bit pattern to be of another type. +Casts are done with the ``cast`` operator and force the compiler to +interpret a bit pattern to be of another type. -Type conversions are a much more polite way to convert a type into another: +Type conversions are a much more polite way to convert a type into another: They preserve the abstract *value*, not necessarily the *bit-pattern*. If a type conversion is not possible, the compiler complains or an exception is -raised. +raised. The syntax for type conversions is ``destination_type(expression_to_convert)`` -(like an ordinary call): +(like an ordinary call): .. code-block:: nimrod - proc getID(x: TPerson): int = + proc getID(x: TPerson): int = return TStudent(x).id - -The ``EInvalidObjectConversion`` exception is raised if ``x`` is not a + +The ``EInvalidObjectConversion`` exception is raised if ``x`` is not a ``TStudent``. @@ -134,7 +134,7 @@ An example: .. code-block:: nimrod - # This is an example how an abstract syntax tree could be modelled in Nimrod + # This is an example how an abstract syntax tree could be modeled in Nimrod type TNodeKind = enum # the different node types nkInt, # a leaf with an integer value @@ -171,12 +171,12 @@ object fields raises an exception. Methods ------- -In ordinary object oriented languages, procedures (also called *methods*) are -bound to a class. This has disadvantages: +In ordinary object oriented languages, procedures (also called *methods*) are +bound to a class. This has disadvantages: -* Adding a method to a class the programmer has no control over is +* Adding a method to a class the programmer has no control over is impossible or needs ugly workarounds. -* Often it is unclear where the method should belong to: Is +* Often it is unclear where the method should belong to: is ``join`` a string method or an array method? Nimrod avoids these problems by not assigning methods to a class. All methods @@ -192,7 +192,7 @@ The syntax ``obj.method(args)`` can be used instead of ``method(obj, args)``. If there are no remaining arguments, the parentheses can be omitted: ``obj.len`` (instead of ``len(obj)``). -This `method call syntax`:idx: is not restricted to objects, it can be used +This `method call syntax`:idx: is not restricted to objects, it can be used for any type: .. code-block:: nimrod @@ -217,9 +217,9 @@ So "pure object oriented" code is easy to write: Properties ---------- -As the above example shows, Nimrod has no need for *get-properties*: -Ordinary get-procedures that are called with the *method call syntax* achieve -the same. But setting a value is different; for this a special setter syntax +As the above example shows, Nimrod has no need for *get-properties*: +Ordinary get-procedures that are called with the *method call syntax* achieve +the same. But setting a value is different; for this a special setter syntax is needed: .. code-block:: nimrod @@ -229,23 +229,23 @@ is needed: FHost: int # cannot be accessed from the outside of the module # the `F` prefix is a convention to avoid clashes since # the accessors are named `host` - - proc `host=`*(s: var TSocket, value: int) {.inline.} = + + proc `host=`*(s: var TSocket, value: int) {.inline.} = ## setter of hostAddr s.FHost = value proc host*(s: TSocket): int {.inline.} = ## getter of hostAddr return s.FHost - - var + + var s: TSocket s.host = 34 # same as `host=`(s, 34) (The example also shows ``inline`` procedures.) -The ``[]`` array access operator can be overloaded to provide +The ``[]`` array access operator can be overloaded to provide `array properties`:idx:\ : .. code-block:: nimrod @@ -261,15 +261,15 @@ The ``[]`` array access operator can be overloaded to provide of 2: v.z = value else: assert(false) - proc `[]`* (v: TVector, i: int): float = + proc `[]`* (v: TVector, i: int): float = # getter case i of 0: result = v.x of 1: result = v.y of 2: result = v.z else: assert(false) - -The example is silly, since a vector is better modelled by a tuple which + +The example is silly, since a vector is better modelled by a tuple which already provides ``v[]`` access. @@ -336,9 +336,9 @@ dispatching: collide(a, b) # output: 2 -As the example demonstrates, invokation of a multi-method cannot be ambiguous: -Collide 2 is prefered over collide 1 because the resolution works from left to -right. Thus ``TUnit, TThing`` is prefered over ``TThing, TUnit``. +As the example demonstrates, invocation of a multi-method cannot be ambiguous: +Collide 2 is preferred over collide 1 because the resolution works from left to +right. Thus ``TUnit, TThing`` is preferred over ``TThing, TUnit``. **Perfomance note**: Nimrod does not produce a virtual method table, but generates dispatch trees. This avoids the expensive indirect branch for method @@ -349,20 +349,20 @@ evaluation or dead code elimination do not work with methods. Exceptions ========== -In Nimrod `exceptions`:idx: are objects. By convention, exception types are -prefixed with an 'E', not 'T'. The ``system`` module defines an exception +In Nimrod `exceptions`:idx: are objects. By convention, exception types are +prefixed with an 'E', not 'T'. The ``system`` module defines an exception hierarchy that you might want to stick to. Exceptions should be allocated on the heap because their lifetime is unknown. -A convention is that exceptions should be raised in *exceptional* cases: +A convention is that exceptions should be raised in *exceptional* cases: For example, if a file cannot be opened, this should not raise an exception since this is quite common (the file may not exist). Raise statement --------------- -Raising an exception is done with the ``raise`` statement: +Raising an exception is done with the ``raise`` statement: .. code-block:: nimrod var @@ -371,14 +371,14 @@ Raising an exception is done with the ``raise`` statement: e.msg = "the request to the OS failed" raise e -If the ``raise`` keyword is not followed by an expression, the last exception -is *re-raised*. +If the ``raise`` keyword is not followed by an expression, the last exception +is *re-raised*. Try statement ------------- -The `try`:idx: statement handles exceptions: +The `try`:idx: statement handles exceptions: .. code-block:: nimrod # read the first two lines of a text file that should contain numbers @@ -403,11 +403,11 @@ The `try`:idx: statement handles exceptions: finally: close(f) -The statements after the ``try`` are executed unless an exception is -raised. Then the appropriate ``except`` part is executed. +The statements after the ``try`` are executed unless an exception is +raised. Then the appropriate ``except`` part is executed. The empty ``except`` part is executed if there is an exception that is -not explicitely listed. It is similiar to an ``else`` part in ``if`` +not explicitly listed. It is similar to an ``else`` part in ``if`` statements. If there is a ``finally`` part, it is always executed after the @@ -422,9 +422,9 @@ is not executed (if an exception occurs). Generics ======== -`Generics`:idx: are Nimrod's means to parametrize procs, iterators or types +`Generics`:idx: are Nimrod's means to parametrize procs, iterators or types with `type parameters`:idx:. They are most useful for efficient type safe -containers: +containers: .. code-block:: nimrod type @@ -434,7 +434,7 @@ containers: data: T # the data stored in a node PBinaryTree*[T] = ref TBinaryTree[T] # type that is exported - proc newNode*[T](data: T): PBinaryTree[T] = + proc newNode*[T](data: T): PBinaryTree[T] = # constructor for a node new(result) result.dat = data @@ -448,7 +448,7 @@ containers: while it != nil: # compare the data items; uses the generic ``cmp`` proc # that works for any type that has a ``==`` and ``<`` operator - var c = cmp(it.data, n.data) + var c = cmp(it.data, n.data) if c < 0: if it.le == nil: it.le = n @@ -460,13 +460,13 @@ containers: return it = it.ri - proc add*[T](root: var PBinaryTree[T], data: T) = + proc add*[T](root: var PBinaryTree[T], data: T) = # convenience proc: add(root, newNode(data)) iterator preorder*[T](root: PBinaryTree[T]): T = # Preorder traversal of a binary tree. - # Since recursive iterators are not yet implemented, + # Since recursive iterators are not yet implemented, # this uses an explicit stack (which is more efficient anyway): var stack: seq[PBinaryTree[T]] = @[root] while stack.len > 0: @@ -483,19 +483,19 @@ containers: for str in preorder(root): stdout.writeln(str) -The example shows a generic binary tree. Depending on context, the brackets are -used either to introduce type parameters or to instantiate a generic proc, -iterator or type. As the example shows, generics work with overloading: The +The example shows a generic binary tree. Depending on context, the brackets are +used either to introduce type parameters or to instantiate a generic proc, +iterator or type. As the example shows, generics work with overloading: the best match of ``add`` is used. The built-in ``add`` procedure for sequences -is not hidden and used in the ``preorder`` iterator. +is not hidden and used in the ``preorder`` iterator. Templates ========= -Templates are a simple substitution mechanism that operates on Nimrod's -abstract syntax trees. Templates are processed in the semantic pass of the -compiler. They integrate well with the rest of the language and share none +Templates are a simple substitution mechanism that operates on Nimrod's +abstract syntax trees. Templates are processed in the semantic pass of the +compiler. They integrate well with the rest of the language and share none of C's preprocessor macros flaws. To *invoke* a template, call it like a procedure. @@ -509,31 +509,31 @@ Example: assert(5 != 6) # the compiler rewrites that to: assert(not (5 == 6)) -The ``!=``, ``>``, ``>=``, ``in``, ``notin``, ``isnot`` operators are in fact -templates: This has the benefit that if you overload the ``==`` operator, +The ``!=``, ``>``, ``>=``, ``in``, ``notin``, ``isnot`` operators are in fact +templates: this has the benefit that if you overload the ``==`` operator, the ``!=`` operator is available automatically and does the right thing. (Except for IEEE floating point numbers - NaN breaks basic boolean logic.) ``a > b`` is transformed into ``b < a``. -``a in b`` is transformed into ``contains(b, a)``. +``a in b`` is transformed into ``contains(b, a)``. ``notin`` and ``isnot`` have the obvious meanings. Templates are especially useful for lazy evaluation purposes. Consider a -simple proc for logging: +simple proc for logging: .. code-block:: nimrod const debug = True - - proc log(msg: string) {.inline.} = + + proc log(msg: string) {.inline.} = if debug: stdout.writeln(msg) var x = 4 log("x has the value: " & $x) -This code has a shortcoming: If ``debug`` is set to false someday, the quite -expensive ``$`` and ``&`` operations are still performed! (The argument +This code has a shortcoming: if ``debug`` is set to false someday, the quite +expensive ``$`` and ``&`` operations are still performed! (The argument evaluation for procedures is *eager*). Turning the ``log`` proc into a template solves this problem: @@ -541,8 +541,8 @@ Turning the ``log`` proc into a template solves this problem: .. code-block:: nimrod const debug = True - - template log(msg: string) = + + template log(msg: string) = if debug: stdout.writeln(msg) var @@ -558,12 +558,12 @@ The template body does not open a new scope. To open a new scope use a ``block`` statement: .. code-block:: nimrod - template declareInScope(x: expr, t: typeDesc): stmt = + template declareInScope(x: expr, t: typeDesc): stmt = var x: t - - template declareInNewScope(x: expr, t: typeDesc): stmt = + + template declareInNewScope(x: expr, t: typeDesc): stmt = # open a new scope: - block: + block: var x: t declareInScope(a, int) @@ -598,7 +598,7 @@ via a special ``:`` syntax: In the example the two ``writeln`` statements are bound to the ``actions`` parameter. The ``withFile`` template contains boilerplate code and helps to -avoid a common bug: To forget to close the file. Note how the +avoid a common bug: to forget to close the file. Note how the ``var fn = filename`` statement ensures that ``filename`` is evaluated only once. @@ -606,12 +606,12 @@ once. Macros ====== -Macros enable advanced compile-time code tranformations, but they +Macros enable advanced compile-time code transformations, but they cannot change Nimrod's syntax. However, this is no real restriction because -Nimrod's syntax is flexible enough anyway. +Nimrod's syntax is flexible enough anyway. To write a macro, one needs to know how the Nimrod concrete syntax is converted -to an abstract syntax tree (AST). The AST is documented in the +to an abstract syntax tree (AST). The AST is documented in the `macros <macros.html>`_ module. There are two ways to invoke a macro: @@ -676,13 +676,13 @@ Statement Macros Statement macros are defined just as expression macros. However, they are invoked by an expression following a colon. -The following example outlines a macro that generates a lexical analyser from +The following example outlines a macro that generates a lexical analyzer from regular expressions: .. code-block:: nimrod macro case_token(n: stmt): stmt = - # creates a lexical analyser from regular expressions + # creates a lexical analyzer from regular expressions # ... (implementation is an exercise for the reader :-) nil |