mirror of
https://github.com/nim-lang/Nim.git
synced 2026-07-20 16:01:29 +00:00
Further tutorial updates (#5176)
* tut1: added multiline comments * tut2: replaced expr/stmt with untyped/typed * added some more template/macro example * remove immediate pragma from example
This commit is contained in:
13
doc/tut1.rst
13
doc/tut1.rst
@@ -125,6 +125,19 @@ Documentation comments are tokens; they are only allowed at certain places in
|
||||
the input file as they belong to the syntax tree! This feature enables simpler
|
||||
documentation generators.
|
||||
|
||||
Multiline comments are started with ``#[`` and terminated with ``]#``. Multiline
|
||||
comments can also be nested.
|
||||
|
||||
.. code-block:: nim
|
||||
#[
|
||||
You can have any Nim code text commented
|
||||
out inside this with no indentation restrictions.
|
||||
yes("May I ask a pointless question?")
|
||||
#[
|
||||
Note: these can be nested!!
|
||||
]#
|
||||
]#
|
||||
|
||||
You can also use the `discard statement`_ together with *long string
|
||||
literals* to create block comments:
|
||||
|
||||
|
||||
87
doc/tut2.rst
87
doc/tut2.rst
@@ -557,7 +557,7 @@ To *invoke* a template, call it like a procedure.
|
||||
Example:
|
||||
|
||||
.. code-block:: nim
|
||||
template `!=` (a, b: expr): expr =
|
||||
template `!=` (a, b: untyped): untyped =
|
||||
# this definition exists in the System module
|
||||
not (a == b)
|
||||
|
||||
@@ -603,19 +603,20 @@ Turning the ``log`` proc into a template solves this problem:
|
||||
x = 4
|
||||
log("x has the value: " & $x)
|
||||
|
||||
The parameters' types can be ordinary types or the meta types ``expr``
|
||||
(stands for *expression*), ``stmt`` (stands for *statement*) or ``typedesc``
|
||||
(stands for *type description*). If the template has no explicit return type,
|
||||
``stmt`` is used for consistency with procs and methods.
|
||||
The parameters' types can be ordinary types or the meta types ``untyped``,
|
||||
``typed``, or ``typedesc``.
|
||||
``typedesc`` stands for *type description*, and ``untyped`` means symbol lookups and
|
||||
type resolution is not performed before the expression is passed to the template.
|
||||
|
||||
If there is a ``stmt`` parameter it should be the last in the template
|
||||
declaration. The reason is that statements can be passed to a template
|
||||
via a special ``:`` syntax:
|
||||
If the template has no explicit return type,
|
||||
``void`` is used for consistency with procs and methods.
|
||||
|
||||
To pass a block of statements to a template, use 'untyped' for the last parameter:
|
||||
|
||||
.. code-block:: nim
|
||||
|
||||
template withFile(f: expr, filename: string, mode: FileMode,
|
||||
body: stmt): stmt {.immediate.} =
|
||||
template withFile(f: untyped, filename: string, mode: FileMode,
|
||||
body: untyped): typed =
|
||||
let fn = filename
|
||||
var f: File
|
||||
if open(f, fn, mode):
|
||||
@@ -636,7 +637,6 @@ avoid a common bug: to forget to close the file. Note how the
|
||||
``let fn = filename`` statement ensures that ``filename`` is evaluated only
|
||||
once.
|
||||
|
||||
|
||||
Macros
|
||||
======
|
||||
|
||||
@@ -672,7 +672,7 @@ variable number of arguments:
|
||||
# ``macros`` module:
|
||||
import macros
|
||||
|
||||
macro debug(n: varargs[expr]): stmt =
|
||||
macro debug(n: varargs[untyped]): typed =
|
||||
# `n` is a Nim AST that contains a list of expressions;
|
||||
# this macro returns a list of statements (n is passed for proper line
|
||||
# information):
|
||||
@@ -723,7 +723,7 @@ regular expressions:
|
||||
|
||||
.. code-block:: nim
|
||||
|
||||
macro case_token(n: stmt): stmt =
|
||||
macro case_token(n: typed): typed =
|
||||
# creates a lexical analyzer from regular expressions
|
||||
# ... (implementation is an exercise for the reader :-)
|
||||
discard
|
||||
@@ -815,7 +815,7 @@ modified source code implementing the macro:
|
||||
|
||||
import macros, strutils
|
||||
|
||||
macro readCfgAndBuildSource(cfgFilename: string): stmt =
|
||||
macro readCfgAndBuildSource(cfgFilename: string): typed =
|
||||
let
|
||||
inputString = slurp(cfgFilename.strVal)
|
||||
var
|
||||
@@ -941,7 +941,7 @@ macro:
|
||||
|
||||
import macros, strutils
|
||||
|
||||
macro readCfgAndBuildAST(cfgFilename: string): stmt =
|
||||
macro readCfgAndBuildAST(cfgFilename: string): typed =
|
||||
let
|
||||
inputString = slurp(cfgFilename.strVal)
|
||||
|
||||
@@ -992,6 +992,63 @@ example you add ``echo treeRepr(result)`` you should get the same output as
|
||||
using the ``dumpTree`` macro, but of course you can call that at any point of
|
||||
the macro where you might be having troubles.
|
||||
|
||||
Example Templates and Macros
|
||||
============================
|
||||
|
||||
Lifting Procs
|
||||
+++++++++++++
|
||||
|
||||
.. code-block:: nim
|
||||
import math
|
||||
|
||||
template liftScalarProc(fname) =
|
||||
## Lift a proc taking one scalar parameter and returning a
|
||||
## scalar value (eg ``proc sssss[T](x: T): float``),
|
||||
## to provide templated procs that can handle a single
|
||||
## parameter of seq[T] or nested seq[seq[]] or the same type
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## liftScalarProc(abs)
|
||||
## # now abs(@[@[1,-2], @[-2,-3]]) == @[@[1,2], @[2,3]]
|
||||
proc fname[T](x: openarray[T]): auto =
|
||||
var temp: T
|
||||
type outType = type(fname(temp))
|
||||
result = newSeq[outType](x.len)
|
||||
for i in 0..<x.len:
|
||||
result[i] = fname(x[i])
|
||||
|
||||
liftScalarProc(sqrt) # make sqrt() work for sequences
|
||||
echo sqrt(@[4.0, 16.0, 25.0, 36.0]) # => @[2.0, 4.0, 5.0, 6.0]
|
||||
|
||||
Identifier Mangling
|
||||
+++++++++++++++++++
|
||||
|
||||
.. code-block:: nim
|
||||
proc echoHW() =
|
||||
echo "Hello world"
|
||||
proc echoHW0() =
|
||||
echo "Hello world 0"
|
||||
proc echoHW1() =
|
||||
echo "Hello world 1"
|
||||
|
||||
template joinSymbols(a, b: untyped): untyped =
|
||||
`a b`()
|
||||
|
||||
joinSymbols(echo, HW)
|
||||
|
||||
macro str2Call(s1, s2): typed =
|
||||
result = newNimNode(nnkStmtList)
|
||||
for i in 0..1:
|
||||
# combines s1, s2 and an integer into an proc identifier
|
||||
# that is called in a statement list
|
||||
result.add(newCall(!($s1 & $s2 & $i)))
|
||||
|
||||
str2Call("echo", "HW")
|
||||
|
||||
# Output:
|
||||
# Hello world
|
||||
# Hello world 0
|
||||
# Hello world 1
|
||||
|
||||
Compilation to JavaScript
|
||||
=========================
|
||||
|
||||
Reference in New Issue
Block a user