*x?y:z*operator). So what about a thin abstraction (wrapper) around this recurring pattern?

proc func {name argl body} {proc $name $argl [list expr $body]}(Might have called it

*fun*as well... it sure is.) That's all. A collateral advantage is that all expressions are braced, without me having to care. But to not make the page look so empty, here's some examples for

*func*uses:

func fac n {$n<2? 1: $n*[fac [incr n -1]]} func gcd {u v} {$u? [gcd [expr $v%$u] $u]: $v} func min {a b} {$a<$b? $a: $b} func sgn x {($x>0)-($x<0)} ;# courtesy rmaxPity we have to make expr explicit again, in nested calls like in

*gcd*... But

*func*isn't limited to math functions (which, especially when recursive, come out nice), but for expr uses in testing predicates as well:

func atomar list {[lindex $list 0] eq $list} func empty list {[llength $list] == 0} func in {list element} {[lsearch -exact $list $element] >= 0} func limit {x min max} {$x<$min? $min: $x>$max? $max: $x} func ladd {list e} {[in $list $e]? $list: [lappend list $e]}Exposing expr operators as Tcl commands goes quite easy too:

foreach op {+ * / %} {func $op {a b} "\$a $op \$b"}For "-", we distinguish unary and binary form:

func - {a {b ""}} {$b eq ""? -$a: $a-$b}Having the modulo operator exposed, gcd now looks nicer (from Playing with rationals):

func gcd {u v} {$u? [gcd [% $v $u] $u]: abs($v)}For unary

*not*I prefer that name to "!", as it might also stand for factorial - and see the shortest function body I ever wrote :^) :

func not x {!$x}It could have been shortened by one byte, though :^)

func not x !\$xFeel free to add more meaningful examples! In any case, no one can blame me for not using return in these sweet one-liners... :)Without big mention, functions implemented by recursion have a pattern for which

*func*is well suited (see

*fac*and

*gcd*above). Another example is this integer range generator (starts from 1, and is inclusive, so [iota1 5] == {1 2 3 4 5}):

func iota1 n {$n == 1? 1: [concat [iota1 [- $n 1]] $n]}

AM (1 june 2004) I have been musing over another, related subject:

- Define functional relations between variables (possibly defining an equation)
- Use high-level commands to actually solve the equation

RS 2006-01-25: If you have many parameters as global variables, you can extend func to import all of them. This runs the risk of side-effects, but here you go:

proc func {name argl body} { proc $name $argl "eval global \[info globals\]; expr {$body}" }Testing:

% set a 6 6 % func f x {$x * $a} % f 7 42

Arts and crafts of Tcl-Tk programming