TCL use "eq" or "==" when the argument can be a list or a string

14,021

Solution 1

You seem to be getting in a bit of a pickle there. Firstly, you probably don't want to use expr inside the if condition, so this will be enough:

if { $Node_3 eq "BadAngle" } {
    return "BadAngle"
}

Since one of the things you are comparing against is definitely non-numeric, you'll be fine using the eq operator though the == operator is equivalent. The only time there is a difference is when both operands look like numbers, when == will compare them as numbers (parsing them into numbers if necessary). This means that "1" == "0x01" despite them being rather different strings; the eq operator always compares as strings.

How to choose which is best? It's actually pretty easy: do you think you are working with numbers at this point on both sides of the comparison? If yes, use ==, and otherwise use eq.


The one time you want to use expr inside if is when you're dynamically selecting the operator. This is not really recommended, but you'd do it like this:

set op "=="
if { [expr {$Node_3} $op {"BadAngle"} ]} {
    return "BadAngle"
}

It's pretty ugly. (Notice that I put everything else inside its own braces to prevent double evaluation, and I'm careful with balancing all the brackets correctly, which is what was tripping you up in the code in your question.) Don't do it unless you really really need to.

Solution 2

You have two distinct problems in your attempts:

  1. In the first example you're trying to call expr in a wrong way: if (and other commands which support conditions, such as while) use the same machinery to evaluate their condition the expr command does — to cite the manual:

    The if command evaluates expr1 as an expression (in the same way that expr evaluates its argument).

    Now that machinery sees a bare word "expr" and has no idea what to do with it.

    There are two ways to fix the code:

    • Wrong way — properly call expr:

       if {[expr {$Node_3 eq "BadAngle"}]} { ... }
      

      This is wrong because the nested call to expr is purely superficial.

    • Correct way — just drop unneeded expr:

       if {$Node_3 eq "BadAngle"} { ... }
      
  2. In the second example you decided to make the situaton more complicated by introducing another boolean test (not needed as the eq and == operators already return a value of type boolean). But in this case you forgot to put the closing curly brace, }, which performs grouping, for the code should have been

    if { [ expr { $Node_3 eq "BadAngle" } ] == 1 } } { ... }
    

In any case the correct solution is to simply use

if {$Node_3 eq "BadAngle"} { ... }
Share:
14,021
Lumpi
Author by

Lumpi

Updated on June 14, 2022

Comments

  • Lumpi
    Lumpi almost 2 years

    I have the following if loop:

    if { expr { $Node_3 eq "BadAngle" } } {
      return "BadAngle"
    }
    

    Node_3 can be a list containing coordinates, or the simple string "BadAngle" I use TCLPro 1.4 for debugging and TCL 8.6. I get:

    *syntax error in expression " expr { $Node_3 eq "BadAngle" } "*

    I then also tried:

    if { [ expr { $Node_3 eq "BadAngle" ] == 1 } } {
       return "BadAngle"
    }
    

    But i get the same error. Also: What is the better alternative in this case: To use "==" or "eq", I think "eq" because a list is a kind of a string..or?