EMZETT.
Login

Kurz: Mit coroutine unterbrechen und fortsetzen Prozeduren ihre Arbeit – ideal für Generatoren:

Teil des Kurses Tcl

Kapitel 7 von 8 im Kurs Tcl. Mit Fortschritt, Quiz und Zertifikat auf der Lernseite.

Coroutinen

Mit coroutine unterbrechen und fortsetzen Prozeduren ihre Arbeit – ideal für Generatoren:

proc generator {} {
    yield
    for {set i 1} {$i <= 5} {incr i} { yield [expr {$i * $i}] }
    return -code break
}
 
coroutine quadrate generator
while 1 {
    set wert [quadrate]
    puts -nonewline "$wert "
    if {[catch {quadrate} _]} break
}
puts ""
 
proc fib_gen {} {
    yield
    set a 0; set b 1
    while 1 {
        yield $a
        lassign [list $b [expr {$a + $b}]] a b
    }
}
coroutine fib fib_gen
for {set i 0} {$i < 10} {incr i} { puts -nonewline "[fib] " }
puts ""
rename fib {}

Ausgabe:

1 9 25
0 1 1 2 3 5 8 13 21 34

Traces

Mit trace reagiert man auf Zugriffe, Änderungen oder Prozeduraufrufe:

proc beobachte {name index op} {
    upvar 1 $name var
    puts "  $name geändert: $var"
}
set wert 0
trace add variable wert write beobachte
set wert 5
incr wert
set wert 42
trace remove variable wert write beobachte
set wert 99
puts $wert
 
proc rechne {a b} { return [expr {$a * $b}] }
trace add execution rechne enter {apply {{cmd op} { puts "  -> ruft $cmd" }}}
puts [rechne 6 7]

Ausgabe:

wert geändert: 5
  wert geändert: 6
  wert geändert: 42
99
  -> ruft rechne 6 7
42

Befehle umbenennen und Introspektion

rename puts alt_puts
proc puts {text} {
    alt_puts [string toupper $text]
}
puts "hallo welt"
rename puts {}
rename alt_puts puts
puts "wieder normal"
 
proc beispiel {a {b 2} args} {}
puts [info args beispiel]
puts [info default beispiel b wert]
puts $wert
puts [info exists ::tcl_version]
puts [info level]
proc tief {} { return [info level] }
puts [tief]
puts [expr {[lsearch [info commands] while] >= 0}]

Ausgabe:

HALLO WELT
wieder normal
a b args
1
2
1
0
1
1

Sichere Interpreter

Unvertrauenswürdigen Code führt man in einem Safe Interpreter aus:

set sicher [interp create -safe]
puts [$sicher eval {expr {6 * 7}}]
puts [$sicher eval {string toupper "ok"}]
if {[catch {$sicher eval {exec ls}} fehler]} { puts "blockiert: $fehler" }
if {[catch {$sicher eval {open /etc/passwd}} fehler]} { puts "blockiert: $fehler" }
$sicher alias hallo apply {{x} { return "Hallo, $x!" }}
puts [$sicher eval {hallo Mia}]
interp delete $sicher

Ausgabe:

42
OK
blockiert: invalid command name "exec"
blockiert: invalid command name "open"
Hallo, Mia!

Merke

  • coroutine und yield bauen Generatoren und kooperative Abläufe
  • trace überwacht Variablen und Befehle
  • Befehle lassen sich mit rename ersetzen; info liefert Introspektion
  • Safe Interpreter führen fremden Code mit eingeschränkten Rechten aus

Übungsaufgabe

Baue einen Generator, der nacheinander Primzahlen liefert.

Quiz zur Selbstkontrolle

Weiter im Kurs

Zurück: Praxisprojekte

Weiter: Referenz und Spickzettel

Alle Kapitel: Tcl im Überblick