Version 14 of eq

Updated 2011-11-10 21:07:27 by dkf

Infix operator for string comparison inside expr. Returns true if its arguments are string-equal.

Its opposite part is ne which returns true if its arguments are not string-equal.

Differs from == in such that its arguments cannot be treated as numerical values, so 1 == 1.0 returns true, but 1 eq 1.0 returns false.

Example:

% expr {"a" eq "b"}
0
% expr {"a" ne "b"}
1

Also comparing text with eq is faster than ==.

AMG: Efficiency is a secondary concern. Correctness comes first. Your program will misbehave, sometimes in non-obvious ways, if you use == when you need eq or vice versa. When you're comparing strings, use eq. When you're comparing numbers, use ==. Numbers can be equivalent yet have different string representations; strings can be different yet have the same numerical representation. "\t1.e0" == "0x001\n". Luckily, in this case the correct thing is also the fast thing.


BC: Which is more efficient - string compare or eq?

AMG: time to the rescue!

proc 1 {a b} {expr {$a eq $b}}
proc 2 {a b} {::tcl::mathop::eq $a $b}
proc 3 {a b} {string compare $a $b}
proc 4 {a b} {string equal $a $b}
set a "\t1.e0"
set b "0x001\n"
time {1 $a $b} 1000000 ;# 1.633135 microseconds per iteration
time {2 $a $b} 1000000 ;# 1.619685 microseconds per iteration
time {3 $a $b} 1000000 ;# 1.618814 microseconds per iteration
time {4 $a $b} 1000000 ;# 1.612457 microseconds per iteration

It's a wash; the difference is nanoseconds. The actual eq operator (2) takes about the same amount of time as string compare (3). Embedding eq into an expr adds some overhead, which you pay for anyway if you're using if, while, for, or other math and logic.

string compare is closer to ne in behavior; both return 0 when the strings are equal. string equal is the closest command to eq. string compare and string equal both have options that eq and ne do not.


DAB: The timings on this page don't take the "if" condition into account. "if" is automatically calling "expr", so "if{string equal}" is calling one extra command.

Code:

proc 1 {a b} {if {$a eq $b} {return 1}}
proc 2 {a b} {if {[string equal $a $b]} {return 1}}
set a "\t1.e0"
set b "0x001\n"
puts [time {1 $a $b} 1000000] ;# 1.101801 microseconds per iteration
puts [time {2 $a $b} 1000000] ;# 1.230454 microseconds per iteration

Using this pattern, "eq" is about 10% faster.