How to make a swap method for a structure?

I have two structures of type XYZ that i want to swap.

I defined the method

Private Sub swap(byref t1 as XYZ, byref t2 as XYZ)
  dim tmp as XZY
  tmp = t1
  t1 = t2
  t2 = tmp  
End Sub

However when complied I get this error message:

You can’t pass an expression as a parameter that is defined as ByRef
if triindex = &h0E then swap(tri.p(0), tri.p(2))

Structures (If I remember correctly) are essentially memory blocks , and I have a suspicion that they would already be ‘by ref’

Do you want to make the date pointed to by tri.p(0) swap with the data that was held in tri.p(2),
leaving the pointers alone?
Or do you want to make the pointer in tri.p(0) and the pointer in tri.p(2) change places, leaving the data where it was?

If you pass pointers into the Swap, then you are only sending Integers, and they are fine as byRef parameters.

Things are weird here.

I made a sample to see what’s going on and got even more weird things:

Test Structure:

Shared array with 2 of them in a class

A proven working swap method:

COMPILER BUGS? or just a Riddle?

maybe because the structure is part of the window?

Good catch, let’s see.

Most things are gone. But the original question shows up.

I think that’s a compiler bug. An indexed content is not a “calculated value” that can’t be referenced.

Open an Issue report with a simple sample and let’s see what they say or fix the issue.

1 Like

looks like a bug because
var a as tri.xy can go to this method.


Public Sub swap(t as tri, a as integer, b as integer)
  Var c As tri.xy = t.p(a)
End Sub

I see. your a and b are indexes. And the vector as parameter.

What we don’t know is if he tracks indexes in a vector or is just handling complex sparse data as nodes in a tree.

This has nothing to do with a structure. Remove the byref‘s in the swap method parameters and it should work as expected.

The swap won’t occur because the “virtual” swap will occur with copies.

ByRef remains one of the more conceptually difficult concepts in Xojo.

ByRef takes a reference to a variable or property that holds a value, allowing you to manipulate the contents of that variable or property in a method. As such, you must pass a variable or property, not an array element or static value.

If you want a method that swaps array elements, take the array and indexes as mentioned above.

ByRef illustration:

Sub M1( a As Integer )
  a = 5
End Sub

Sub M2 ( ByRef a As Integer )
  a = 5
End Sub

var x as integer = 2
M1( x ) // x remains 2
M2( x ) // The method has changed the contents of x to 5
1 Like

So the fundamental issue with passing someArray(index) to a ByRef parameter is that you’re not actually passing something with its own memory address. The array itself (someArray) has a memory address because it is an object in its own right but the elements contained within do not, at least when you refer to them via index. This also applied to class properties (someObject.someProperty).

Essentially, anything you want to pass to a ByRef parameter must be declared by Dim or Var in the scope local to the call containing the ByRef.

That is not how references to objects Work. Objects are pased as Value because the “value” that is pased is just a POINTER to the object, not the object itself or a copy of it.

Actually YES, it is if you are using ByRef. You are “calculating” the pointer to the pointer of the object/Array

however this should be equal

var p0 as xy
var p2 as xy

swap(tri.p(0), tri.p(2)) ← compiler error
swap(p0, p2) ← works

Were talking about structures, not instances of classes.

Using Byref:

After swap:

Without ByRef (ByVal):

No Swap:

:face_with_symbols_over_mouth: Sure, you are so right.

Is it worth mentioning that if the structure is turned into a class (even if the class simply wraps the structure), then the class can be given a .clone method.

Var  tempz as new XYZ
tempz.clone (tri.p(0))
tri.p(0).clone (tri.p(1))
tri.p(1).clone (tempz)

sub Clone( fromitem as XYZ)
x = fromitem.x
y = fromitem.y
end sub

For a Structure, this is unnecessary as a mere assignment creates a “clone”.

var s1 as MyStructure
s1.Prop = 1

var s2 as MyStructure = s1
s2.Prop = 2

// s1.Prop is still 1

Oh my… :slight_smile: I seem to have started a thread!!!
This is what happens when you code at 2AM.

Looking at the code, it does seem like a bad idea to pass an array element by ref or not.
Although judging by some of the comments it seems like maybe a better approach would have been to pass the a triangle to a method called swap and let it change the Points in the array.

I seem to remember in C there was a SWAP that was inline and typeless.

I am considering converting the structure to a class adding a method to it.

Thanks all for the support!!!

In C we can swap structures in a vector, that’s why you remember. Seems like Xojo opted to make it impossible.