[Richard Suchenwirth] - Another little investigation into [Tcl and Lisp]. Lisp's classic conditional, COND, takes any number of argument lists, where the first element is an expression, and evaluates to the first argument whose condition resulted in not-NIL. As an idiom, the last (default) condition often is just T, standing for "true" in Lisp. Example: ======none (SETQ SGN (COND ((> X 0) 1) ((< X 0) -1) (T 0) )) ====== In contrast, Tcl's [if] does not return a value (wrong, see below), so cannot be used directly in an assignment. Rather, one would have to write ====== if {$x>0} { set sgn 1 } elseif {$x<0} { set sgn -1 } else { set sgn 0 } ====== [glennj]: actually, [if] does return a value -- it's just tricky to find a command that returns a value without other side effects like setting a variable: ====== set x [if {1} {expr 42} {expr 24}] ;# ==> x is now 42 set y [if {0} {expr 42} {expr 24}] ;# ==> y is now 24 ====== [RS]: As very quick hack, I use [subst] - but identity is easily written in Tcl, of course: ====== proc is x {set x} puts [if {$x} {is yes} else {is no}] ====== ---- There is one shortcut, though: [expr] inherits from C also the peculiar x?y:z operator, which implements "if x then y else z" and can also be nested, so the above case could concisely be rewritten as ====== set sgn [expr {$x>0? 1 : $x<0? -1 : 0}] ====== This is quite powerful, as you can spread the braced argument to [expr] over several lines: ====== set sgn [expr { $x>0? 1 : $x<0? -1 : 0 }] ====== Just (as often in expr), the syntax is so un-Tclish... We can also emulate COND like this: ====== proc cond {args} { if {[llength $args]==1} {set args [lindex $args 0]} foreach {condition body} $args { if {[uplevel 1 expr $condition]} { return [uplevel 1 [list expr $body]] } } } ====== with some modifications: arguments come alternating as condition and value, but may as a whole be braced to avoid backslashing; for truth constant, Tcl's 1 (or in fact any non-zero number) is taken in place of ''T''. Examples: ====== set sgn [cond {$x>0} 1 {$x<0} -1 {1} 0] ====== or ====== set sgn [cond { {$x>0} 1 {$x<0} -1 {1} 0 }] ====== which looks almost as tidy as the LISP original. For performance reasons, better stay with [expr] however - the above cond vs. expr implementations, each wrapped in a proc, took 1070 vs. 60 microseconds on my old home P200, so good old [expr] appears to be 17 times faster... More examples in [Binary trees]. ---- See also [In case of: select, another switch] <> Arts and crafts of Tcl-Tk programming | Control Structure