What am I misunderstanding about arrays?

I see a behavior that surprised me — and I honestly didn’t think it’s been working this way unless I’m going crazy. But maybe you can explain this to me. I have an array named Board which is 8x8.

Var tempBoard(7, 7) As String = board
tempBoard(7,7) = “X”
tempBoard(7,6) = “X”
tempBoard(7,5) = “X”
tempBoard(7,4) = “X”

This code is setting positions 7,7 through 7,4 in tempBoard to “X,” just like I expected.
But it’s also setting the values 7,7 through 7,4 in. Board to “X.” So I’m guessing that tempBoard and Board are sharing a memory location.

But why? Why wasn’t tempBoard initialized as an independent variable? I can work around it by running through a loop that copies the values from board to tempBoard. But I’d like to understand why it’s behaving like this.

In your declaration for the array, you are assigning it the value of board. An array is an object, and it obeys all the normal rules about references. The variables tempBoard and board point to the same array object in your code, so any modifications affect the same object.

3 Likes

In my opinion (not shared by everyone) Xojo Arrays are “weird” with some complicated behavior - in short, it’s not always obvious when a new array object is or is not created.

You may find this discussion interesting: Xojo WTF

A new array is created when you declare it, call the Array function, or call ToArray. I may have missed another method creating a new array but these would be the main ways.

1 Like

Another way is to use ParamArray — Xojo documentation

Public Function Foobar(ParamArray x as Integer) As integer()
  return x  // in this function, x is a newly created array containing the parameters
End Function

var xx() as Integer = Foobar(1,2,3)

And here’s a follow-up question now.

I’ve also assumed that if I pass an array as a parameter to a subroutine, I’m passing it by value and not by memory location. And if I change a member of the array in the routine, the change is not carried back to the calling routine.

Passing an Array to a Method: By Ref or Not

And your assumption would be incorrect. You are passing a reference to the array, not a copy of it.

in Xojo, the Array object itself is always passed by reference, so a function gets a pointer to the actual array, and any changes made in the function are visible on the original array outside the function.

You can also pass the Array parameter ByRef but this means something different: inside a function with a ByRef Array parameter, the function can change the actual reference itself.

Imagine this:


Public Sub foo(x() as integer)
  x(0) = 99
  x = nil // this has no effect outside the function
End Sub
var a() as integer = Array(1,2,3)

Call foobar(a)  // now a() contains (99,1,3)

vs. using ByRef

Public Sub bar(ByRef x() as integer)
  x = Array(7,8,9)
End Sub

var a() as integer = Array(1,2,3)
var b() as integer = a  // b is a reference, pointing to a()

Call bar(b)

// at this point, 
// a and b now point to different array objects
// a = (7,8,9)
// b = (1,2,3) 

Subtle, but important difference.

3 Likes

That’s fair. But remember that we’re dealing with a home-grown compiler. It’s bound to have some quirks.

I think the documentation could be better, for example this section (link):

var names(2), copyNames(2) As String
names = Array("Fred", "Ginger", "Stanley")
copyNames = names

The last statement assigns the values of all three elements of names to the first three elements of copyNames. If copyNames had fewer elements than names, then additional elements would first be added to copyNames and the assignment of all the elements of names to copyNames would be completed.

To me this is unclear, and can be read to imply that the array values are copied, but that’s not what happens.

Between reading these replies and reading the thread that was linked to, I have no idea at all what to expect when I pass an array to a routine. It’s probably the terminology that gets me confused. I’ll just go test it for myself.

1 Like

why is it unclear?

1 Like

Arrays are great for prototyping, but usually you will write better code by defining a custom Class:

  • a Class can have a proper Constructor()
  • a Class controls access: private data and methods can be hidden from the public
  • a Class can have Shared properties which are shared among all instances of a class
  • a Class can implement handy methods such as Operator_Convert() which can convert to/from other data types.
  • a Class can implement a .Clone() or .Copy() method which makes a new copy of itself.

See Class properties, methods and events — Xojo documentation

Xojo uses the LLVM compiler these days. It translates your Xojo down to an intermediate representation that is then compiled to bytecode by LLVM. (Note that the Android platform uses a completely different system)

This decision is one of the best they ever made - sitting on top of LLVM has allowed us to inherit all the benefits of ongoing LLVM development without Xojo having to roll it themselves. It is why we have XojoScript, for starters. :grin:

2 Likes

You are passing it by reference. One important aspect of the Xojo language is that it does not make copies of objects for you. Wherever you pass around an object, you are passing a reference to it. Xojo will not make a copy of an array, for example, whereas it will make a copy of an intrinsic like integer or color.

The documentation claims otherwise: “If copyNames had fewer elements than names, then additional elements would first be added to copyNames and the assignment of all the elements of names to copyNames would be completed.” There is no implication; the documentation explicitly states that all the elements get copied and the receiving array is redimensioned first to make sure they all fit.

LLVM did not replace the Xojo compiler, it enhances it. The Xojo compiler produces an intermediate format that is fed to LLVM.

That is a really unfortunate description in the documentation. It does go on to say that the 2 variables point to the same array in the next paragraph, but the section you quote is very misleading.

1 Like

Right, but this is simply not true : the array items are never copied.

What happens is simply the reference for one array is replaced by the other one.

The end result is basically the same as what’s described, but the process described is incorrect.

1 Like