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.)

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