manual: many additions and improvements

This commit is contained in:
Andreas Rumpf 2018-04-14 14:53:31 +02:00
commit 8c09ffd36d

View file

@ -598,6 +598,16 @@ whitespace (this parsing change was introduced with version 0.13.0):
echo($foo) echo($foo)
Spacing also determines whether ``(a, b)`` is parsed as an the argument list
of a call or whether it is parsed as a tuple constructor:
.. code-block:: nim
echo(1, 2) # pass 1 and 2 to echo
.. code-block:: nim
echo (1, 2) # pass the tuple (1, 2) to echo
Grammar Grammar
------- -------
@ -953,8 +963,8 @@ provides for ``string`` representation.
proc `$`(p: Person): string = # `$` always returns a string proc `$`(p: Person): string = # `$` always returns a string
result = p.name & " is " & result = p.name & " is " &
$p.age & # we *need* the `$` in front of p.age, which $p.age & # we *need* the `$` in front of p.age which
# is natively an integer, to convert it to # is natively an integer to convert it to
# a string # a string
" years old." " years old."
@ -1176,6 +1186,18 @@ of the assignment operator is described in `type-bound-operations-operator`_.
# the same, but less readable: # the same, but less readable:
person = ("Peter", 30) person = ("Peter", 30)
A tuple with one unnamed field can be constructed with the parentheses and a
trailing comma:
.. code-block:: nim
proc echoUnaryTuple(a: (int,)) =
echo a[0]
echoUnaryTuple (1,)
In fact, a trailing comma is allowed for every tuple construction.
The implementation aligns the fields for best access performance. The alignment The implementation aligns the fields for best access performance. The alignment
is compatible with the way the C compiler does it. is compatible with the way the C compiler does it.
@ -3237,21 +3259,28 @@ with the *method call syntax* achieve the same. But setting a value is
different; for this a special setter syntax is needed: different; for this a special setter syntax is needed:
.. code-block:: nim .. code-block:: nim
# Module asocket
type type
Socket* = ref object of RootObj Socket* = ref object of RootObj
FHost: int # cannot be accessed from the outside of the module host: 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 Socket, value: int) {.inline.} = proc `host=`*(s: var Socket, value: int) {.inline.} =
## setter of hostAddr ## setter of hostAddr.
s.FHost = value ## This accesses the 'host' field and is not a recursive call to
## ``host=`` because the builtin dot access is preferred if it is
## avaliable:
s.host = value
proc host*(s: Socket): int {.inline.} = proc host*(s: Socket): int {.inline.} =
## getter of hostAddr ## getter of hostAddr
s.FHost ## This accesses the 'host' field and is not a recursive call to
## ``host`` because the builtin dot access is preferred if it is
## avaliable:
s.host
.. code-block:: nim
# module B
import asocket
var s: Socket var s: Socket
new s new s
s.host = 34 # same as `host=`(s, 34) s.host = 34 # same as `host=`(s, 34)
@ -3298,7 +3327,7 @@ visible in both places). The closure environment may be allocated on the heap
or on the stack if the compiler determines that this would be safe. or on the stack if the compiler determines that this would be safe.
Creating closures in loops Creating closures in loops
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~
Since closures capture local variables by reference it is often not wanted Since closures capture local variables by reference it is often not wanted
behavior inside loop bodies. See `closureScope <system.html#closureScope>`_ behavior inside loop bodies. See `closureScope <system.html#closureScope>`_
@ -3321,6 +3350,20 @@ Procs as expressions can appear both as nested procs and inside top level
executable code. executable code.
Func
----
The ``func`` keyword introduces a shortcut for a `noSideEffect`:idx: proc.
.. code-block:: nim
func binarySearch[T](a: openArray[T]; elem: T): int
Is short for:
.. code-block:: nim
proc binarySearch[T](a: openArray[T]; elem: T): int {.noSideEffect.}
Do notation Do notation
----------- -----------
@ -4132,8 +4175,7 @@ The following example shows a generic binary tree can be modelled:
proc newNode*[T](data: T): BinaryTree[T] = proc newNode*[T](data: T): BinaryTree[T] =
# constructor for a node # constructor for a node
new(result) result = BinaryTree(le: nil, ri: nil, data: data)
result.data = data
proc add*[T](root: var BinaryTree[T], n: BinaryTree[T]) = proc add*[T](root: var BinaryTree[T], n: BinaryTree[T]) =
# insert a node into the tree # insert a node into the tree
@ -4179,7 +4221,8 @@ The following example shows a generic binary tree can be modelled:
for str in preorder(root): for str in preorder(root):
stdout.writeLine(str) stdout.writeLine(str)
The ``T`` is called a `generic type parameter`:idx:. The ``T`` is called a `generic type parameter`:idx: or
a `type variable`:idx:.
Is operator Is operator
@ -6258,30 +6301,12 @@ As a special semantic rule, the built-in `debugEcho <system.html#debugEcho>`_
pretends to be free of side effects, so that it can be used for debugging pretends to be free of side effects, so that it can be used for debugging
routines marked as ``noSideEffect``. routines marked as ``noSideEffect``.
**Future directions**: ``func`` may become a keyword and syntactic sugar for a ``func`` is syntactic sugar for a proc with no side effects:
proc with no side effects:
.. code-block:: nim .. code-block:: nim
func `+` (x, y: int): int func `+` (x, y: int): int
destructor pragma
-----------------
The ``destructor`` pragma is used to mark a proc to act as a type destructor.
Its usage is deprecated, see `type bound operations`_ instead.
override pragma
---------------
See `type bound operations`_ instead.
procvar pragma
--------------
The ``procvar`` pragma is used to mark a proc that it can be passed to a
procedural variable.
compileTime pragma compileTime pragma
------------------ ------------------
The ``compileTime`` pragma is used to mark a proc or variable to be used at The ``compileTime`` pragma is used to mark a proc or variable to be used at
@ -6348,7 +6373,9 @@ memory, but nothing worse happens.
final pragma final pragma
------------ ------------
The ``final`` pragma can be used for an object type to specify that it The ``final`` pragma can be used for an object type to specify that it
cannot be inherited from. cannot be inherited from. Note that inheritance is only available for
objects that inherit from an existing object (via the ``object of SuperType``
syntax) or that have been marked as ``inheritable``.
shallow pragma shallow pragma
@ -6363,7 +6390,7 @@ structure:
.. code-block:: nim .. code-block:: nim
type type
NodeKind = enum nkLeaf, nkInner NodeKind = enum nkLeaf, nkInner
Node {.final, shallow.} = object Node {.shallow.} = object
case kind: NodeKind case kind: NodeKind
of nkLeaf: of nkLeaf:
strVal: string strVal: string
@ -6850,7 +6877,7 @@ underlying C ``struct`` in a ``sizeof`` expression:
.. code-block:: Nim .. code-block:: Nim
type type
DIR* {.importc: "DIR", header: "<dirent.h>", DIR* {.importc: "DIR", header: "<dirent.h>",
final, pure, incompleteStruct.} = object pure, incompleteStruct.} = object
Compile pragma Compile pragma
@ -6983,7 +7010,7 @@ pragmas this allows *sloppy* interfacing with libraries written in C++:
irr = "<irrlicht/irrlicht.h>" irr = "<irrlicht/irrlicht.h>"
type type
IrrlichtDeviceObj {.final, header: irr, IrrlichtDeviceObj {.header: irr,
importcpp: "IrrlichtDevice".} = object importcpp: "IrrlichtDevice".} = object
IrrlichtDevice = ptr IrrlichtDeviceObj IrrlichtDevice = ptr IrrlichtDeviceObj
@ -7006,7 +7033,7 @@ via the ``namespace::identifier`` notation:
.. code-block:: nim .. code-block:: nim
type type
IrrlichtDeviceObj {.final, header: irr, IrrlichtDeviceObj {.header: irr,
importcpp: "irr::IrrlichtDevice".} = object importcpp: "irr::IrrlichtDevice".} = object
@ -7129,8 +7156,8 @@ Wrapping destructors
Since Nim generates C++ directly, any destructor is called implicitly by the Since Nim generates C++ directly, any destructor is called implicitly by the
C++ compiler at the scope exits. This means that often one can get away with C++ compiler at the scope exits. This means that often one can get away with
not wrapping the destructor at all! However when it needs to be invoked not wrapping the destructor at all! However when it needs to be invoked
explicitly, it needs to be wrapped. But the pattern language already provides explicitly, it needs to be wrapped. The pattern language provides
everything that is required for that: everything that is required:
.. code-block:: nim .. code-block:: nim
proc destroyFoo(this: var Foo) {.importcpp: "#.~Foo()".} proc destroyFoo(this: var Foo) {.importcpp: "#.~Foo()".}
@ -7297,7 +7324,7 @@ pragma description
const FooBar {.intdefine.}: int = 5 const FooBar {.intdefine.}: int = 5
echo FooBar echo FooBar
.. code-block:: bash ::
nim c -d:FooBar=42 foobar.c nim c -d:FooBar=42 foobar.c
In the above example, providing the -d flag causes the symbol In the above example, providing the -d flag causes the symbol
@ -7452,7 +7479,7 @@ instructs the compiler to pass the type by value to procs:
.. code-block:: nim .. code-block:: nim
type type
Vector {.bycopy, pure.} = object Vector {.bycopy.} = object
x, y, z: float x, y, z: float