Posted to tcl by aspect at Wed Nov 23 23:05:31 GMT 2016view pretty
proc proc* {name arglist body} { set upargs [lsearch -inline -all $arglist _*] if {[llength $upargs]} { set upvar [list ::upvar 1] foreach a $upargs { append upvar " \$$a [list [string range $a 1 end]]" } set body "$upvar;$body" } tailcall ::proc $name $arglist $body } # clamp saves some tedium and getting max/min confused proc* clamp {_x min max} { if {$x < $min} {set x $min} if {$x > $max} {set x $max} return $x } # incrmod 10 i 3 -> 0 3 6 9 2 5 8 1 4 7 .. proc* incrmod {modulus _var {increment 1}} { set var [expr {($var + $increment) % $modulus}] } # assertions, if nothing else, are a nice default error message proc assert {x {msg ""}} { if {![uplevel 1 expr [list $x]]} { catch { set y [uplevel 1 [list subst -noc $x]] if {$y ne $x} { set x "{$y} from {$x}" } } throw ASSERT "[concat "Assertion failed!" $msg] $x" } } proc test {} { set a 12 assert {[clamp a 0 10] == 10} assert {[clamp a 5 15] == 10} assert {[clamp a 12 20] == 12} assert {[incrmod 12 a 1] == 1} } test