Passing an Array to a Method: By Ref or Not

In the documentation, I was unable to find anything about using ByRef in this context except a note:

Passing array parameters with ByRef is not currently supported for Android.

____

Elsewhere:

Arrays are treated as objects so be aware that assigning an array to another variable or passing an array as a parameter does not make a copy of the array. Instead you get a new variable that points to the original array so any changes you make to the “2nd” array also affect the first array.

My question: Is there a difference between passing an array ByRef or not bothering with the ByRef?

Sub Foo(a() As Integer)

or

Sub Foo(ByRef a() As Integer)

The AIs (Claude/ChatGPT/Gemini), at least part of the time, insist that there is. I do not know if this notion is “leaked” over from some other language or is true in Xojo.

That depends on what you need to do with the parameter (array). If the method called does not specify the modifier ByRef, then it gets a copy of the array (passed as a parameter) as is explained in the documentation. You can read the array passed, but if you modify the contents, you modify the copied array, the original is not modified.

If you need to modify the array that gets past, then use ByRef. Except for Android.

HTH

No. The documentation specifically says the opposite: that an array is always treated as an object when passed as a parameter to a method. Xojo will not create copies of arrays for you.

Here’s a decent Xojo blog post demonstrating this fact:

3 Likes

Norman has very strong opinions on this topic, if you can seek out his advice…

Yes, they are slightly different. Consider this code in your hypothetical method:

Var NewArray() as Integer

a=NewArray

If you pass a() without ByRef, you are getting a fresh reference to that array passed to your method. Reassigning it with a=NewArray only affects the code in the method, because that is the scope of the reference. When the method exits, the array that was passed to the method is unchanged.

If you pass a() WITH ByRef, any assignments you make to that variable will be reflected outside of the method’s scope, because you are working with the reference itself. Upon returning from the method, the variable referencing the array will now point to NewArray.

2 Likes

I read the blog post from Norman Palardy in you previous post. It says :

Recall that ByRef is needed when you want to change the instance referred to. And in this case that isn’t what we’re doing. We’re altering the contents, but not the instance itself. We’re not replacing the entire array with a new one.

According to this, without ByRef, the instance in the calling code would not be modified.

The moral of the story – ByRef is used when you want to alter the actual item. When its a value type like an integer this alters the value it holds. When its a reference type this would allow you to assign a new instance.

Maybe I have semantic wrong, but the conclusion is using ByRef,the initial instance - in the calling code - is changed. I get that the initial instance now points to a different array.

Now what’s puzzling is that before Norman says :

And indeed the values changed do remain when we get back to the caller. Why is this the case? We didn’t use ByRef and still could alter the array?

What am I missing, arrays are implicitly passed ByRef ?

I had thought that they were implicitly passed ByRef, and that assumption has never bitten me.

The AI’s claim that in Xojo that is not the case.

Sub Foo(a() As Integer)

will allow you to change the values of the individual elements, and those changes will be preserved when the Method completes. However, if you change the structure of the array, for example, by calling a.ResizeTo(10), that change will not be persistent in the calling environment once the Method completes.

____

To accomplish this goal (resizing),

Sub Foo(ByRef a() As Integer) is required. Then, if you change the size of the array, it will change in the environment that launched the Method.

All this was unfamiliar to me. I assumed that when an array was passed, the Method had complete control over it in Xojo. But I was unable to find a discussion of this in the Documentation. Hence the original question.

I swear… we need to start tagging posts where the question is prompted by AI bull**** causing confusion.

This is not true. You do not need the ByRef to do the resizing in the method. You only need ByRef if you want to change what array the outside variable refers to.

1 Like

The AIs are wrong. If you pass an array by value you are effectively passing a reference to the array. When the method called changes individual elements, resizes the array, or both, all of that will affect the array you’ve passed. You will see these changes after the method has returned.

If you pass the array by reference, a reference to a reference gets passed. The difference is that the method called could assign a different array to the parameter and when it returns, the array in the calling method will have changed to that array as well. That – and just that – can’t happen when you pass the array by value.

Passing an array by value means that you will end up with the same object although its contents and size may have have changed completely. Passing it by reference means that you could end up with a different object.

5 Likes

Thank you for answering the question accurately, based on my limited testing after reading your answer. For me, it was enlightening.

we need to start tagging posts where the question is prompted by AI bull**** causing confusion.

Perhaps, but shouldn’t we also tag questions when incompleteness of the Documentation causes confusion?:slightly_smiling_face: I am familiar with inaccurate information from AI’s, but I had difficulty in this case with trying to understand the difference between passing a() vs ByRef a() once the AI’s raised the issue in my mind.

I had always just passed a() and never given it a second thought, and I had never run into trouble.

I had no luck trying to clarify the issue by looking at the documentation.

It interests me that all three of the AI’s that I consulted (Claude ChatGPT Gemini) gave me the same wrong answer.

I appreciate the forum.

File a ticket! There’s a category for Documentation.

Next time, ask the forum first. :slight_smile:

1 Like

Arrays and objects are reference types. So when you don’t use ByRef, what gets passed for a value type is a copy of the value. For a reference type, a copy of the reference is passed. Since it’s still a reference, you can access and modify the original array or object through it.

commonly we never write ByVal the system choose self what is needed for the non value types.

ByVal is the default so if you don’t explicitly demand ByRef you will always get ByVal. There’s not even a choice to be made.

Having said that, arguments of type string, object, dictionary, or array are always passed as a reference and this is independent of the ByVal/ByRef distinction. It’s rather that passing a string, object, dictionary, or array creates another level of indirection. Passing an array ByVal passes a reference (one level of indirection) while passing it ByRef passes a reference to a reference to the actual array (two levels of indirection).

By the way, as strings are immutable a string’s contents cannot be changed even when just a reference to the string is passed. If you could change a string passed ByVal this would affect the original string, just like it would affect an array, object, or dictionary – only Xojo doesn’t support changing strings so it can’t happen. Still it is useful to keep in mind that when you have a huge string and pass it ByVal this won’t take up huge amounts of memory to create a copy; only the reference gets copied.

1 Like

i think ByVal list() As String should raise an error, same for ByVal a As Class1

This is quite misleading and needs to be called out. When used with an object such as an array, ByVal passes a new reference to the object, leaving the original reference out of scope to the method and preventing it from being altered. ByRef passes the original reference, placing it in scope to the method and allowing it to be modified.

2 Likes

In both cases the values are changed, but in a case the objects are different. Whether the object is the same ore not, does it care ? What is important is the values are changed. Having a pointer or a pointer to a pointer caries the same result. If it’s the way it is implemented, then IMHO it’s a horrible mess. Then arrays should always be passed ByRef, don’t you think ?

@Paul_Lefebvre , can you comment on this about reference and reference to a reference ? Thanks

It isn’t. This isn’t at all how it works. Please see my reply to another poster (above) for a succinct explanation.

How is that different from what I was saying?

Suppose you send your kid to school and and when it returns it has learned something it didn’t knew before, i.e. it has changed but it’s still your kid. That’s how passing an array or object ByVal works. But what if the kid that returns from school was actually a different kid? That’s what can happen if you are passing the array or object ByRef.

1 Like

In your comment, you mention “reference to a reference” and layers of indirection. There are no layers of indirection in ByRef or ByVal. In both cases, you are handed a reference that is a direct reference – you do not follow a chain of references to access an object like you might in a language that uses pointers and handles.

This may seem like semantics, but this is a case where using precise terminology is important, because users of other languages (like C++) could easily make assumptions about Xojo that aren’t correct, based on the usage of language that has specific meanings in their other language’s context.

1 Like