The difference between eq and ==
Starting with Tcl 8.4, expr (and its cousins if, while and for) includes the operators "eq" and "ne". The documentation, though accurate, doesn't present much of a distinction between those and their counterparts "==" and "!=".
From the expr man page [1]:
- == !=
- Boolean equal and not equal. Each operator produces a zero/one result. Valid for all operand types.
- eq ne
- Boolean string equal and string not equal. Each operator produces a zero/one result. The operand types are interpreted only as strings.
So what's the difference? The definition for eq and ne mention that the operand types are interpreted "only as strings" but how do == and != treat the operands? One must closely read the man page to learn that Tcl will attempt to do perform a numerical interpretation of the operands if at all possible, falling back to strings if either operand can't be interpreted as a number.
Thus, with == and != Tcl will do a numerical comparison if possible, and a string comparison otherwise. With eq and ne Tcl will always perform a string comparison. The difference can be significant, as illustrated in the example below:
set v1 "01"
set v2 "1"
if {$v1 == $v2} {puts "equal"} else {puts "not equal"}
if {$v1 eq $v2} {puts "equal"} else {puts "not equal"}
When you run the above example you should see "equal" followed by "not equal". In this case, the choice of operators is critical as the result between the two are exact opposites.
Practical Advice
If you know you want to do string comparisons, prior to Tcl 8.4 you either had to use == or != and rely on both operands not looking like numbers, or resort to using a string function such as "string equal", "string compare", "string match" or "regexp". The careful programmer would always use one of those functions, especially if the comparison was done on external data not under direct control of the program.
Starting with 8.4 we can now use the eq and ne operators any time we want to coerce the comparison to be done on the string representation of the operands. This guarantees that a numerical comparison won't happen in an edge case while making the program arguably easier to read then when using a string function to do the comparison.