Version 23 of if

Updated 2002-03-25 08:41:25

The reference page for if can be found at http://purl.org/tcl/home/man/tcl8.4/TclCmd/if.htm

if is a part of the Tcl core distribution.

The standard way of performing a test and executing a script depending on the result. I happen to believe that the following [if] commands are good style, and this is because the styles minimise the number of backslashes (a problem if you insist on putting open braces at the start of a line out of some belief that Tcl has to look like C) and maximise the comprehensibility and readability at a local level (where you need an otherwise clause, always mark it with else, and where the start of the then clause is not on the same line as the condition that guards it, always mark it with then - it is better to have a multi-line condition than it is to have one monster that wraps round several times.)

DKF


 # Standard simple if
 if {some condition} {
    # Note that the open-brace for the body is on the same line
    # as the if-command and condition.

    some conditionally executed script...
 }

 # Standard simple if with else clause
 if {some condition} {
    some conditionally executed script.
 } else {
    some script to execute if the condition isn't satisfied.
 }

 # Standard multi-test if
 if {first condition} {
    thing to do if the first condition succeeds
 } elseif {second condition} {
    thing to do if the first fails, but the second condition succeeds
 }

 # Handling complex (i.e. long) conditions
 if {
     this condition stretches over
     multiple lines
 } then {
     thing to do if the condition succeeds
 }

Sample of boolean operators:

 set a 1
 set b "stuff"
 if { $a == 1 ||
      [string equal $b "nonsense" ] } { puts "found" }

This demonstrates that one can test two (or more) expressions within the if {} expr1 . Note that in the second test, a Tcl command is executed and the result is tested for true or false. In both cases, as soon as the entire if expr1 can be determined true or false, processing stops. This is sometimes called 'short circuiting'. The good news is that it permits you to write things like:

   if a particular variable exists &&
      a tcl command called using that function returns true
      do something special
   else
      we get here because the particular variable didn't exist.

The bad news, as such, is that you have to be certain that you use the right boolean connector between the parts. The && requires that all parts of the if expr1 are true. The || requires only that one of them be true.


Intuitive logical operators: You can use "and" for && and "or" for || if you use this preprocessor (accepts arguments like real if, but preprocessing works so far only on the first condition):

 proc If {cond args} {
        regsub -all " and " $cond {\&\&} cond
        regsub -all " or " $cond {||} cond
        uplevel 1 if [list $cond] $args
 } ;#RS

In Tcl, if is a function, not just a control construct. Its result is that of the then or else clause, whichever executes.

 set y [if {$x} {list a} {list b}]

$y will be "a" if $x evaluates to true, or "b" if $x evaluates to false.

expr's ?: operator does similar things.

 set y [expr {"foo"=="bar" ? "yes" : "no"}]

- SCT & RS


Why do if's expressions use curly brackets? Dollar signs and square brackets are processed, obviously, and everything appears to work a lot like a quoted string. What gives? Just sugar? Admittedly, a lot of coders would be scared off by quoted conditionals, but I'm curious. FW

RS: Curly braces are used to group their contents into one "word" without first-round evaluation. The contents will be evaluated unchanged by expr, which is optimized in speed, e.g. for accesses to variables. On the other hand, it does not accept all conditions that will be accepted as pure strings (operators in variables, "dot cast"...) Especially for string constants, bracing is important to prevent parsing away quote signs. You can omit braces if the condition is one "word" already (i.e. does not contain whitespace). The first three are equivalent (though the first two may be slower):

 if $foo==1     {puts YES} ;#(1)
 if "$foo == 1" {puts YES} ;#(2)
 if {$foo == 1} {puts YES} ;#(3)
 if ""==""      {puts YES} ;#(4)
 ERROR: extra characters after close-quote

So: you may do without curlies around if conditions, but they are recommended and sometimes required - not by if, but by the Tcl way.


LV asks: does the evaluation of the if expr1 differ from an invocation of the expr command? If so, in what ways?

RS: I think seen from Tcl, they behave similarly - not sure about the implementation in the byte code compiler. But there is a difference in for, whose second arg is also an expr-like condition:

 for {set x $from} {[expr $from $op $to]} {...

If you want to retrieve operators from variables, you have to write an explicit, unbraced expr, which is evaluated as wanted, and returns 0 or 1, which is then evaluated by for's invocation of expr-like code...

rmax: The additional [expr] can be avoided. You just have to make sure, that the operator (but nothing else) gets substituted before [for]'s second argument sees it:

 for {set x $from} "\$from $op \$to" {...

A discussion of when in an if to use == vs using some other way of comparing two variables needs to be made either here on on its own page string compare ....


See also expr problems with int.


Tcl syntax help - Arts and crafts of Tcl-Tk programming - Category Command