Andreas
Andreas

Reputation: 5301

How to test for improper use of expr == on strings?

Using == in expr can lead to unintended behavior for strings that also qualify as doubles. One example being if {$a == $b} when a=1.0 and b=1. I imagine the reason == even works for strings post 8.4 is backwards compatibility with scripts that haven't replaced it with eq yet.

Is there a (simple) way to detect this at runtime, possibly finding all erroneous uses during test? Like activating a "strict" mode or something?

Upvotes: 1

Views: 83

Answers (2)

Schelte Bron
Schelte Bron

Reputation: 4813

The operators known in Tcl (except &&, ||, and ? :) are available in the tcl::mathop namespace. Unfortunately, contrary to functions in the tcl::mathfunc namespace, redefining tcl::mathop::== has no effect on the way expr treats '=='.

I'm afraid the only way to do what you're asking, short of changing the Tcl C code, would be to redefine expr and other commands that take arithmetic expressions as arguments (if, for, while). Parse the expression arguments, splitting it in parts on either side of the ==, while taking order of precedence into account. Then pass each part through the original expr and check if the results fulfill string is double -strict.

This is not a trivial exercise and will probably also considerably slow down the execution of your script.

Upvotes: 1

Donal Fellows
Donal Fellows

Reputation: 137567

Tcl, by design, has no such simple way to check. (In 8.6 onwards, there's an unsupported command, tcl::unsupported::representation, which can do part of the check, but it doesn't really do what you want, especially with literals.) The real issue is that in the logical type-system of Tcl, strings are a supertype of all other value types and all other value types are thus serializable as strings and that's guaranteed to work (provided you have enough memory).

But there are ways to enforce numeric-ness by doing operations which require numbers, and the simplest is probably to just add the unary + in front of the arguments:

if {+$x == +$y} { ...

Enforcing integer-ness can be done with $x | 0 or $x ^ 0. There's not usually any need to enforce floating-point-ness as distinct from numeric-ness. If you really need it, string is has the various checks you need but they're probably going to be expensive.


All the above work in all versions of Tcl from this millennium, except where explicitly noted.

Upvotes: 1

Related Questions