Runtime type detection
SOLVED
tl;dr how can you tell if a number is really a string
The original question has been updated/improved.
Equality comparisons on floating point numbers will produce different results...
"1.1"=1.1 //is true!
"0.1"=0.1 //is not true :(
This second comparison can be fixed with...
+"0.1"=+0.1 // is true!
The problem is, what if we don't realise that a value is a stringy number, or just overlook implementing this defensive check.
One solution would be to lint check %Float properties and return types that should originate from a number and not a string, as discussed here...
https://community.intersystems.com/post/compilation-gotchas-and-request-change
A second approach is to use Unit Testing to ensure not only the values of a test are the same, but also the types of those values.
If for instance, a method should return a value of type %Float, then instead of using a normal AssertEquals() method, the unit test could implement an AssertFloatEquals() or AssertNumberEquals() which would check the return value is a pure number and not a stringy number. This would fix problems upstream before they can happen.
So, boiling all of this down, how can you tell if a number is really a string.
A simple condition for the solution should produce a false (zero) for both of these tests
$$$AssertNumberEquals("0.1",0.1)
$$$AssertNumberEquals("1.1",1.1)
Answers that are not hitting the mark...
1. Implement (+a=+b) in the AssertNumberEquals() method.
This will create a false positive test for (+"0.1"=+0.1), the point is that these need to fail. It also opens up tests to incorrectly pass values such as "1B" and 1.
2. Use "sort by", such that "0.12345"]]$c(0) returns 1 and 0.12345]]$c(0) returns zero.
Whilst a brilliant and innovative answer, it turns out that it of course only works for floating numbers with a leading zero.
It also turns out that $length(+num)=$length(num) will also do the same thing without the collation problems described below.
3. Use $IsValidNum
Whilst this will determine if a string contains a valid number, it does not tell us if the number is contained within a string.
4. Use ["0.12345"].%GetTypeOf(0) which will return "string"
I got this to work with the latest versions of Caché, but I was unable to find anything that was backwards compatible.