I was reading some of the $languageWTF sites which are amusing and educational, as they talk about edge-cases and weird “footguns” in the languages. For example:
I used to love Python, but reading these has made me appreciate Xojo’s langauge even more - I think Xojo (the langauge) has relatively few of these WTF moments.
Has anyone collected a WTF Xojo page?
If not, how about putting your favorite one here…
For purposes of discussion, let’s limit these purely to weird things in the core Xojo programming language. Let’s stay away from framework, IDE, or per-platform/OS bugs.
Here are a few of mine:
dim d as new dictionary
dim a(0) as integer
for i as integer = 1 to 3
a.ResizeTo(0)
a(0) = i
d.Value(str(i)) = a
next
// what does D contain?
dim j as new JSONItem(d)
log J.ToString
// {"1":[3],"2":[3],"3":[3]}
Diagnosis:
Arrays are weird. They function somewhat like Objects, but unlike Objects you can’t “new” them, and resizing an array does not create a new instance of the array. As a result, the dictionary contains 3 references to the same array.
Solution:
define the array within the loop - variables defined inside a loop are created as new instances for each iteration:
dim d as new dictionary
for i as integer = 1 to 3
dim a(0) as integer
a(0) = i
d.Value(str(i)) = a
next
// what does D contain?
dim j as new JSONItem(d)
log J.ToString
// {"1":[1],"2":[2],"3":[3]}
The point being that Arrays and Strings have different semantics in Xojo - after many years, I’m perfectly used to this and think it makes sense, but it can be unexpected behavior depending on your expectations from other languages…
To be true, strings and arrays have different semantics in 99% of high level languages. They approach each other in lower level languages where both became pointers to mutable contents.
Agree, though if you read about the Python String WTFs, you will be very happy to not run into these issues in Xojo. (Shorter version: in Python, two strings may, or may not refer to the same object, depending on their contents. Ugh)
Variants and the is operator can be a little surprising.
dim s1 as variant = "foo"
dim s2 as variant = "bar"
s2 = "foo"
if s1 = s2 then
log "s1 = s2"
else
log "s1 <> s2"
end if
if s1 is s2 then
log "s1 is s2"
else
log "s1 is not s2"
end if
// output:
// s1 = s2
// s1 is s2
I’m not sure about this one. The documentation for “is” says
The Is operator returns True if object1 and object2 actually refer to the same object. It checks identity, not contents, so it Is not affected by the presence of a comparison operator.
However, if you do this:
dim s1 as variant = "foo"
dim s2 as variant = "bar"
dim a(0) as string = Array("foo")
s2 = a(0)
// output:
// s1 = s2
// s1 is not s2
I wonder if the compiler is optimizing string constants in the first case but not the second?
Also, a variation on the Array one above - turns out the Array() function does create a new array instance:
dim d as new dictionary
dim a() as integer
for i as integer = 1 to 3
a = Array(i)
d.Value(str(i)) = a
next
// what does D contain?
dim j as new JSONItem(d)
log J.ToString
// {"1":[1],"2":[2],"3":[3]}
Presumably the take-away is that if one is presented with a variant whose known content is a string, and the intention is to further manipulate the string, it’s best to copy it to a string first.
So instead of converting the 100 to a Uint32 for the comparison , the compiler converts Value to integer? Not great behavior…
When I first started with REALBAsic , there were no unsigned datatypes.
On Bob’s old blog I made a comment about UInts types seemed to be bolted onto the framework and not well integrated. A former Xojo engineer that was involved in adding them to the framework (maybe Aaron?) , basically agreed… which is why one finds such edge cases still all these years later.
Xojo does not take sign in consideration when evaluating expressions, it assumes everything as signed values, so if the sign bit is set in a unsigned positive value it becomes a negative value being evaluated. I would say a bug. Old one.