Kurz: type MeinFehler = object of CatchableError
Teil des Kurses Nim
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)Ausgabe:
3
Eigener Fehler: negativ: -1
aufgeräumt
ValueError: invalid integer: abc
Indexfehler abgefangen
durch null
5 -1Option
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)Ausgabe:
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 quadrateAusgabe:
x 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, " ", summeAusgabe:
4000 4000Der 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
Übungsaufgabe
Schreibe ein Template unless, das einen Block ausführt, wenn eine Bedingung falsch ist.
Quiz zur Selbstkontrolle
?
- Werte, die fehlen können, ohne nil (richtig)
- Optionale Parameter
- Kommandozeilenoptionen
- Konfigurationsdateien
Was erzeugt ein template?
- Code durch Textersetzung zur Übersetzungszeit (richtig)
- Eine Klasse
- Einen Thread
- Eine Datei
Wie schützt man gemeinsamen Zustand in Threads?
- Mit Lock/withLock oder Atomic (richtig)
- Gar nicht nötig
- Mit echo
- Mit block
Weiter im Kurs
Zurück: Strings, Dateien und Datenformate
Weiter: Praxisprojekte
Alle Kapitel: Nim im Überblick