Xojo WTF

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]}

Now the Dictionary contains 3 different arrays.

1 Like

Well, the behavior shown is what I would expect, so not a WTF?

2 Likes

Strings are also a bit weird

dim a as string = "Alpha"
dim b as string = a
b = "Beta"
log "a=" + a + " b=" + b
// a=Alpha b=Beta

Strings are immutable and assignment creates a new String.

Compare this to Arrays, in which 2 array variables can point to the same object:

dim a(0) as string
a(0) = "Alpha"
dim b() as string = a
b(0) = "Beta"
log "a(0)=" + a(0) + " b(0)=" + b(0)
//a(0)=Beta b(0)=Beta

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…

The behavior shown is the same behavior of the first case, array related, not string related. To me, Strings aren’t weird.

3 Likes

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)

The pointed Python cases are really WTF cases. Erratic, non expected, inconsistent behaviors depending on Python versions and string contents.

Another WTF is that Operator_Convert — Xojo documentation can get you into trouble. Discussed a number of times previously. Some of the “gotchas” are:

  • Operator_Convert in a superclass can return an instance of a subclass
  • Operator_Convert creates a new object instance, but does not call Constructor(). This can lead to instances that are not properly initialized.
  • Operator_Convert with nil objects can be confusing, for example see Xojo: Account Login
1 Like

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]}

Seems kind of the same Python quirk. The compiler used a pointer to the same internally “fused” in just one literal.

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.

I just prefer it working as expected instead.

You mean you would like a variant which contains a string to behave idenically to a string?

I mean that manual states that

Var a As Variant = 0 // One variant variable
Var b As Variant = 0 // Another variant variable
Var r As Variant

should end as

r = a = b // True
r = a is b // False

But it ends as

r = a = b // True
r = a is b // True, as if(a is a) and not if(a is b)

The same quirk some Python versions have.

Here’s my WTF:

Var Value As UInt32 = 4294967295
If Value > 100 Then
  // Won't Reach Here
End If
7 Likes

This is strange. I wonder how it was translated by Xojo…
Its working if compile in 64bit mode only, but should work in 32bit too

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.

-Karen

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.