|
|
|
 |
Reply From: |
Bernard Cloutier |
That is indeed normal. What was the behaviour you expected?
Here is what’s happening:
Arrays in gdscript can hold a number variants, that is to say any gdscript type (int, float, bool, string, Object, etc.). The append
method means: take this and insert it at the end of the array. Whatever “this” is will be inserted. However, for simple built-in types (int, float, bool, string, vector2…), that means copying their values. For object types (arrays, nodes, other custom types inheriting from Object…), that means copying a reference to that object. That reference is why when you modify array a
, the array a
that was inserted in array b
also gets modified (since it is the same object and not a copy).
I feel that you meant the line b.append(a)
to result in b containing [0, 1, 2]
instead of [[0, 1, 2]]
, right? To obtain this, you’d have to iterate through a and copy each individual element, like so:
func _append_array(target, source):
for elem in source:
target.append(elem)
[Tip: use the curly braces {} icon to get code formatting in your selection]
I was curious because “b.clear()” behaves in one way and “b = ” behaves in another. The first, by the way, eliminates all traces of “b”, even being inside others vars. The second one cleans only “b”.
The confusing thing is that if I put “b” inside “a” (a.append (b)), and then clear “b” with “b.clear()”, any changes I make to b will change it inside a (including b = ). Now if I don’t use .clear () I can do whatever I want with b that doesn’t influence in “a”. This is the behavior that I found strange.
func _on_Button4_pressed():
a.append(6)
a.append(7)
a.append(8)
b.append(a)
print(a) #result = [6, 7, 8]
print(b) #result = [[6, 7, 8]]
a =
print(a) #result =
print(b) #result = [[6, 7, 8]]
It is as if only this “.clear ()” creates a connection between the two vars.
You have to remember that in case of objects, the symbols (aka the names of your vars) are references to an in-memory object.
a = [1, 2, 3]
means “Create the array object [1, 2, 3]
and make a
refer to it”.
b = []
means “Create the array object and make b
refer to it”.
b.append(a)
means “Take the object pointed to by a
and add a reference to it at the end of the array pointed by b
”.
If you’re following, you’ll see that both a
and the first item in the array pointed to by b
refer to the same object, the array [1, 2, 3]
.
Now if you do: a.clear()
, the “clear” method will be applied to the array [1, 2, 3]
, which is also being referenced in the array pointed to by b
. That is why you are seeing the change, not because the clear method creates some sort of magical “connection”.
If you instead do: a = []
, you are saying: “Create another array containing nothing and make a
refer to it”. You won’t see any change in b
, because you’ve only changed what a
points to. Remember that b
doesn’t hold a reference to a
, it only held a reference to the array pointed to by a
, which is still in memory somewhere and is now only being referenced by the first item of the array pointed to by b
(since a
now points to another array object).
In comp sci, we often talk about passing by value or by reference. In the case of gdscript, see this line from the docs:
In GDScript, only base types (int, float, string and the vector types) are passed by value to functions (value is copied). Everything else (instances, arrays, dictionaries, etc) is passed as reference.
source: GDScript: An introduction to dynamic languages — Godot Engine (stable) documentation in English
Bernard Cloutier | 2020-03-02 13:42