Ausnahmen
import std/strutils
type MeinFehler = object of CatchableError
proc pruefe(n: int): int =
if n < 0: raise newException(MeinFehler, "negativ: " & $n)
n
try:
echo pruefe(3)
echo pruefe(-1)
except MeinFehler as e:
echo "Eigener Fehler: ", e.msg
finally:
echo "aufgeräumt"
try:
echo parseInt("abc")
except ValueError as e:
echo "ValueError: ", e.msg
try:
let a = @[1, 2, 3]
echo a[10]
except IndexDefect as e:
echo "Indexfehler abgefangen"
try:
echo 10 div 0
except DivByZeroDefect:
echo "durch null"
proc sicher(a, b: int): int =
try: a div b
except DivByZeroDefect: -1
echo sicher(10, 2), " ", sicher(1, 0)3 Eigener Fehler: negativ: -1 aufgeräumt ValueError: invalid integer: abc Indexfehler abgefangen durch null 5 -1
Option
Statt nil nutzt man Option[T] für Werte, die fehlen können:
import std/options
proc finde(l: seq[int], x: int): Option[int] =
for i, v in l:
if v == x: return some(i)
none(int)
let l = @[5, 3, 9]
let a = finde(l, 9)
let b = finde(l, 7)
echo a, " ", b
echo a.isSome, " ", b.isNone
echo a.get, " ", b.get(-1)
if a.isSome: echo "Index: ", a.get
echo a.map(proc (i: int): int = i * 10)some(2) none(int) true true 2 -1 Index: 2 some(20)
Templates und Makros
Templates sind Textersetzung auf Syntaxebene, Makros bauen Syntaxbäume:
import std/macros
template wiederhole(n: int, rumpf: untyped) =
for _ in 1..n:
rumpf
template mitZeit(name: string, rumpf: untyped) =
echo "Start ", name
rumpf
echo "Ende ", name
template `!=?`(a, b: untyped): bool = a != b
macro verdoppeln(ausdruck: untyped): untyped =
result = quote do:
`ausdruck` * 2
wiederhole(3):
stdout.write "x "
echo ""
mitZeit("Rechnung"):
echo 6 * 7
echo 1 !=? 2
echo verdoppeln(21)
macro zeigeAst(x: untyped): untyped =
echo x.treeRepr
result = newStmtList()
zeigeAst(1 + 2)
const quadrate = block:
var t: array[5, int]
for i in 0 ..< 5: t[i] = i * i
t
echo quadratex x x Start Rechnung 42 Ende Rechnung true 42 [0, 1, 4, 9, 16]
Nebenläufigkeit
import std/[locks, atomics]
var
zaehler: Atomic[int]
sperre: Lock
summe = 0
initLock(sperre)
proc arbeiter(n: int) {.thread.} =
for i in 1..1000:
zaehler.atomicInc
withLock sperre:
summe += 1
var threads: array[4, Thread[int]]
for i in 0 ..< 4:
createThread(threads[i], arbeiter, i)
joinThreads(threads)
echo zaehler.load, " ", summe4000 4000
Der Compiler braucht für Threads den Schalter --threads:on (ab Nim 2 Standard). Für Async-Code gibt es std/asyncdispatch, für Parallelität das Paket malebolgia/taskpools.
Merke
try/except/finallyundraise newException(...)behandeln FehlerOption[T]ersetzt fehlende Werte;some,none,gettemplateundmacroerweitern die Sprache zur Übersetzungszeit- Threads mit
createThread,Lock,Atomic; asynchron mitasyncdispatch
Aufgabe
Schreibe ein Template unless, das einen Block ausführt, wenn eine Bedingung falsch ist.