[Richard Suchenwirth] 2004-05-09 - Functions in Tcl are typically written with the [proc] command. But I notice more and more that, on my way to [functional programming], my proc bodies are a single call to [expr] which does all the rest (often with the powerful ''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 rmax Pity 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 !\$x Feel 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 This seems an excellent way of introducing some physics into the Wiki ;) This is the page I wrote to work out the above ideas: [An equation solver] [WHD]: Would this be a first step toward constraint programming? (A topic that intrigues me, but as yet I know almost nothing about it.) ---- [Arts and crafts of Tcl-Tk programming]