ref does nothing when feeding array elements to a function
-
Consider this code:
// simple structure a = [.x = 1] // put a copy of it into an array b = [a] // modify a (or a clone) by refrence function incByRef(ref a) a.x += 1 return void print ("a.x=", a.x, "\n") incByRef(a) print ("a.x=", a.x, "\n") print ("b[0].x=", b[0].x, "\n") incByRef(b[0]) print ("b[0].x=", b[0].x, "\n") update() sleep(10)
If I haven't made any typos, this prints
a.x=1 a.x=2 b[0].x=1 b[0].x=1
So directly passing 'a' in correctly modifies it in place, but 'b[0]' is left unaltered. Not what I expected, I would have thought b[0].x would get altered as well. Of course, maybe my expectations are wrong or I am doing something wrong.
Workaround for me: In those places where pass by reference is more important than random access, use list-like structures instead. Where random access is important, well...
c = b[0] incByRef(c) b[0] = c
looks horrible and copies the element twice, but works.
-
Looks like a is a global try your function with a different input variable.
-
Ah, right, that pitfall. I'll try to keep that in mind. But nope, changed the argument name of incByRef, no change in the output.
Looks like the fact that 'a' was explicitly declared as an argument was enough information for FUZE to distinguish it from the global. -
-
-
Thanks for the workaround suggestions. However, the real application I had in mind would not be using arrays with a single element, so turning 'b' into a plain copy of 'a' does not help. And the real structures would be potentially large and expensive to copy, and the functions where I would like to call them by ref would do more than just modify a single value.
-
Oops I'm a bit dumb didn't read your comments in the code.
So sorry I'm just trying to work out ref myself. -
Just want to let everyone know I'm currently working on the ref keyword and have my eye on this- Thanks for the report! If anyone has more condensed examples of ref not working as expected I would greatly appreciate them.
-
-
Yup, that's what I'm working on! I've got ref working on my end right now for everything except strings. I still have to test the OP's code with my adjustments, they're doing something I wouldn't have expected.
-
Great! Will it work even if you change the type of the referenced variable inside the called function?
-
Good question. I'll put it on my list of things to test!
-
Following up on this:
The issue is related to the core of how ref works internally, and while ref is currently being worked on, we've determined that this is unfortunately not something we can easily change for the next patch. The limitation in this case is that the ref keyword must be used with a defined non-member, non-element variable. A defined variable is a variable that you've declared and assigned to, which isn't a member or element of an array, structure, sprite, etc.
In the example in the top post,
incByRef(a)
works because it's passinga
, which matches our definition of a defined non-member/non-element variable.incByRef(b[0])
is not currently valid because whileb
is a defined variable,b[0]
doesn't match the criteria (it's an element ofb
). The workaround currently is to write anincArrayElementsByRef(ref my_array)
function that accepts the arrayb
and operates on its elements.We will, however, look at expanding the ref keyword's capabilities in the future. For the next patch we'll clarify this limitation of the ref keyword in the documentation.
-
Hi!
in setTimerfunction increment(ref x) x += 1 return void function doSomething() var test = 0 setTimer(1, 5, increment(test)) loop clear() printAt(0,0, test) update() repeat return void doSomething()
The function is called but test is not "ref" incremented. I noticed this behavior when experimentating with timer. It could be a bug ?
EDIT* it seem that this will be fixed in the next release as raw type don't work when used with ref keyword if I understand. -
That's correct- in version 2.15.0 ref only works with arrays and structures. We're working on expanding it to all variable types for the next patch!
-
@Willpowered Thanks for the explanation! If that is now how the feature is specified, I at least know what to expect. That also explains why 3.0.0 broke this code:
function incByRef(v) v.x = v.x + 1 return a = [.x = 1] b = [.a = a] print("b.a.x=", b.a.x, "\n") incByRef(b.a) // not a defined variable! won't do a thing. print("b.a.x=", b.a.x, "\n")
In 2.1.5, it used to increment b.a.x. Oh well, specs are specs, and at least now things are consistent. I'll be ditching complicated nested data structures I'm used to from other languages and use arrays of primitives and simple structs from now on, that's what the Cool Kids call Data Oriented Design. Many things are even easier to express that way.
-
We're looking at allowing ref to work on structure members and array elements. I'll keep you posted!
-
Will that let us do ‘struct.thing = ref otherstruct.otherthing’?
-
I think it means that you would be able to do something like this:
function increase(ref data) data.value += 1 return void example = [ .member = [ .value = 1 ] ] print(example.member.value, "\n") increase(example.member) print(example.member.value) // currently this value is not updated update() sleep(10)