[Lars H]: I had a look at [Icon Programming Language%|%Icon], and got interested in the unusual approach towards conditionals in that language. Some of that can (of course) be done in Tcl too, so I had a go at it. I find them intereting because they demonstate one way in which one could remove the [expr] "[little language]" from core Tcl (not very useful, but interesting for stylistic reasons). The basic idea is that commands either fail or are successful. When some part of a composite command fails, the whole thing fails, and the other parts of it won't be executed. This is simply the way that Tcl [return] codes work, so we have that already. Failure could be coded as a straightforward [error], but that carries some overhead in constructing the [errorInfo] (or at least some people are very keen on saying it does), so I will use a special '''fail''' command instead. ====== proc fail {} {return -code 5} ====== The relevance this has for control structures ([if], [while], etc.) is that these use the success/fail status of the condition, rather than its value, to decide what to do. Therefore the operations can return something other than the boolean result as value. One example might be ====== proc lcontains {list item} { set n [lsearch -exact $list $item] if {$n>=0} then {return $n} else {fail} } ====== which could be used as ====== f-if {set n [lcontains {red green yellow blue} $col]} { # Success case: puts "This is colour $n." } { # Failure case: puts "I don't know that colour." } ====== Whether this is good style is debatable, but in some cases that order of operations appears natural. A simple implementation is ====== proc f-if {condition then else} { if {![catch {uplevel 1 $condition}]} then { uplevel 1 $then } else { uplevel 1 $else } } ====== and analogously ====== proc f-while {condition body} { while {![catch {uplevel 1 $condition}]} { uplevel 1 $body } } ====== Defining > as another fail-type test, ====== proc > {a b} { if {$a > $b} then { return $b } else { fail } } ====== one can write things like ====== set n 1; set m -3 f-while {> [> 14 $n] $m} { incr n 1; incr m 2 } ====== although that has probably lost much of the beauty in the infix equivalent 14 > $n > $m (14 is greater than ''n'' AND ''n'' is greater than ''m''). ''([escargo] The infix form is the way [Icon] does it, of course.)'' In the construction of elementary operations department, one can note that logical and is simply ; -- a condition can be more than one command, and it only succeeeds if they all succeed. Logical not can be expressed in terms of f-if: ====== proc f-not {condition} {f-if {uplevel $condition} {fail} {}} ====== and then logical or is simply a matter of suitable double negation: ====== proc f-or {args} { f-not { foreach condition $args { f-not {uplevel $condition} } } } ====== ---- [escargo] 2004-01-02: As an old [Icon] programmer, I feel I need to note that in Icon, expressions either '''fail''' or they '''succeed and return a value'''. An expression like ''2 > 11'' fails; ''2 < 11'' succeeds and returns a value of 11. That's why ''2 < 11 < 22'' works. Since < is associative, the expression ''2 < 11'' is evaluated first, returning a value of 11, and then ''11 < 22'' is evaluated. (There are many other aspects of Icon in ''returning a value'' that this does not touch on, such as generators and resumption of expressions. It is a language whose syntax belies its semantic variety.) <> Control Structure | Concept | Icon Programming Language | Syntax