Possible bug with arrays + generic funcs (solved)

Monkey Forums/Monkey Programming/Possible bug with arrays + generic funcs (solved)

Shinkiro1(Posted 2014) [#1]
It might be that I don't completely understand how arrays behave but I assume that the following code:

Function Main:Int()
  Local a:Int[] = [1, 2, 3]
  Local b:Int[] = [5, 5, 5, 5]
  Generic<Int>.Merge(a, b)
  Print a.Length
  Return 0
End

Class Generic<T>

	Function Merge:Void(array1:T[], array2:T[])
		Local offset:Int = array1.Length
		array1 = array1.Resize(array1.Length + array2.Length)
		For Local i:Int = 0 Until array2.Length
			array1[i+offset] = array2[i]
		Next
		Print array1.Length
	End

End

should output 7 twice, but instead I get 7 (inside the Merge function) and then 3 (the original array size).

I thought arrays are passed by reference?


Samah(Posted 2014) [#2]
array1 = array1.Resize(array1.Length + array2.Length)

This creates a new (larger) instance of T[] with the contents of the original array1, and assigns it to the LOCAL array1 parameter.
You're replacing the local reference with your new one, so the original is unchanged.

Edit:
Technically there are no "by reference" arguments in Monkey. True "byref" arguments would allow you to modify the value of the original variable you're passing in, not just the contents of the object. It's the same in Java and many other languages.
C/C++/C# are good examples of byref, because you can actually use pointers (or the "ref" keyword in C#).
It's mostly semantics, but the distinction is important.


Jesse(Posted 2014) [#3]
So true. A possible solution would be this:

Function Main:Int()
  Local a:Int[] = [1, 2, 3]
  Local b:Int[] = [5, 5, 5, 5]
  a = Generic<Int>.Merge(a, b)
  Print a.Length
  Return 0
End

Class Generic<T>

	Function Merge:T[](array1:T[], array2:T[])
		Local offset:Int = array1.Length
		array1 = array1.Resize(array1.Length + array2.Length)
		For Local i:Int = 0 Until array2.Length
			array1[i+offset] = array2[i]
		Next
		Print array1.Length
		Return array1
	End

End

but I am sure you knew that.

array1 is just a local variable pointing to the location of the array. When you resize the array a new array is created and the location passed to the array1 variable. So the original location is removed from the array1 variable and the new location assigned to it. which implies that it no longer points to the original array.

It works the same as with any other parameter in a method or function.


Samah(Posted 2014) [#4]
Jesse's solution is correct.
On a related note, you may want to look at Diddy's Arrays class, as it provides exactly the functionality you are after. It has no dependencies.
http://code.google.com/p/diddy/source/browse/src/diddy/arrays.monkey


Shinkiro1(Posted 2014) [#5]
Wow, thanks for explanation guys, it's very clear to me now.
I completely missed that it becomes a local variable after resizing.


Gerry Quinn(Posted 2014) [#6]
Very common gotcha with arrays, because you *can* pass an array to a function that changes values in it - you just can't have a function that reallocates the array.