What is assigning a value to this variable?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Robbas

Hello!

Something strange is happening, and I think there is something fundamental about Godot I don’t know or understand.

I have this script with function:

func add_item_edit_recipe(value):
print("======= IN ADD ITEM EDIT RECIPE (EDIT RECIPE) =======")
var items = linked_recipe.get_items_in_recipe()
print("RECIPE ITEMS: ", items)
for item in items:
	if value == item:
		print("ITEM ALREADY IN RECIPE")
		return
print("RECIPE ITEMS STILL EMPTY 1??: ", items)
var edit_recipe_item_container_instance = edit_recipe_item_container_scene.instantiate()
vertical_box.add_child(edit_recipe_item_container_instance)
edit_recipe_item_container_instance.set_name(value.get("item_name"))
edit_recipe_item_container_instance.set_unit(value.get("unit"))
recipe_quantities_nodes.append(edit_recipe_item_container_instance.get_quantity_node())
print("RECIPE ITEMS STILL EMPTY 2??: ", items)
recipe_items_in_edit.append(value)
print("RECIPE ITEMS STILL EMPTY 3??: ", items)
print("RECIPE QUANTITY NODE TO ADD: ", recipe_quantities_nodes)
print("RECIPE ITEMS TO ADD: ", recipe_items_in_edit)
print("RECIPE ITEMS STILL EMPTY 4??: ", items)
print("======= END ADD ITEM EDIT RECIPE (EDIT RECIPE) =======")

which yields this output:

======= IN ADD ITEM EDIT RECIPE (EDIT RECIPE) =======
RECIPE ITEMS: []
RECIPE ITEMS STILL EMPTY 1??: []
RECIPE ITEMS STILL EMPTY 2??: []
RECIPE ITEMS STILL EMPTY 3??: [item:<Node2D#111367161045>]
RECIPE QUANTITY NODE TO ADD: [Quantity:<TextEdit#300513494461>]
RECIPE ITEMS TO ADD: [item:<Node2D#111367161045>]
RECIPE ITEMS STILL EMPTY 4??: [item:<Node2D#111367161045>]
======= END ADD ITEM EDIT RECIPE (EDIT RECIPE) =======

It seems like this line: recipe_items_in_edit.append(value) assigns a value to the variable items. How is that possible?

When I create a breakpoint before recipe_items_in_edit.append(value) I see nothing strange going on.

The function that calls the above function is this:

func _on_confirmed():
	print("======= IN ON CONFIRMED (ADD ITEM TO RECIPE LIST) =======")
	if !item_list.is_anything_selected():
		return
	print("ITEM TO ADD IN RECIPE EDIT: ", items[item_list.get_selected_items()[0]])
	linked_instantiator.add_item_edit_recipe(items[item_list.get_selected_items()[0]])
	print("======= END ON CONFIRMED (ADD ITEM TO RECIPE LIST) =======")

The combined output is:

======= IN ON CONFIRMED (ADD ITEM TO RECIPE LIST) =======
ITEM TO ADD IN RECIPE EDIT: item:<Node2D#111367161045>
======= IN ADD ITEM EDIT RECIPE (EDIT RECIPE) =======
RECIPE ITEMS: []
RECIPE ITEMS STILL EMPTY 1??: []
RECIPE ITEMS STILL EMPTY 2??: []
RECIPE ITEMS STILL EMPTY 3??: [item:<Node2D#111367161045>]
RECIPE QUANTITY NODE TO ADD: [Quantity:<TextEdit#300513494461>]
RECIPE ITEMS TO ADD: [item:<Node2D#111367161045>]
RECIPE ITEMS STILL EMPTY 4??: [item:<Node2D#111367161045>]
======= END ADD ITEM EDIT RECIPE (EDIT RECIPE) =======
======= END ON CONFIRMED (ADD ITEM TO RECIPE LIST) =======

What is going on? It’s probably something stupid I’m missing. But how do I troubleshoot this?

Thanks!

You don’t show how/where recipe_items_in_edit is created. I can only assume that both it and your local items are both associated with the same collection…

jgodfrey | 2023-02-05 15:25

Ok, just for my understanding:

var bar = 1
var foo = bar #foo will return 1
bar = 2 #foo is still 1, right? or will foo update to 2?
foo = bar #now foo reutrns 2?

Robbas | 2023-02-05 18:08

Yes, foo will equal 2 at the end of your above script. But, that’s not at all surprising since you’re literally assigning it the current value of bar, which is 2.

More to the point, Array and Dictionary types are passed by reference in Godot. That means when you assign one of these collection types to a variable, you’re not storing a copy of the collection - you’re just storing a reference to it. So, if you change the collection using that new variable, you’re really changing the original collection. So, for example, this:

var arr = [1,2,3,4]
var arr2 = arr
arr2.append(5)
print(arr) 

Note, print arr at the end results in this:

[1, 2, 3, 4, 5]

That’s because arr2 just holds a reference to the original array. So, modifying either arr or arr2 will change the same, single, underlying array.

I assume this is the underlying issue with your question.

If you want a unique copy of such a collection, you can get that via the duplicate() method… So, this:

var arr = [1,2,3,4]
var arr2 = arr.duplicate() # <-- notice the change here
arr2.append(5)
print(arr)

Now, this results in the following:

[1, 2, 3, 4]

… because arr2 now holds a COPY of the original array data, and changing it only changes that copy (and not the original).

jgodfrey | 2023-02-05 18:26

Wow, great thank you!

I think this is the problem!

I will try out using .ducplicate() tomorrow!

Robbas | 2023-02-05 21:09