How to call a function whenever an Array's size changes?

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

I have code I would like to run whenever an Array changes size. I put this into a function:

func _on_drawn_changed():
    %Card.texture = back if drawn.is_empty() else drawn[-1]
    %DeckStatus.text = str(cards.size(), " / ", cards.size() + drawn.size())
    %Draw.disabled = true if cards.is_empty() else false
    %Reset.disabled = true if drawn.is_empty() else false
    %Undo.disabled = true if drawn.is_empty() else false
    %Redo.disabled = true if undone.is_empty() else false

It is nice to have this in one place. However, I don’t like what the code calling it looks like. I have instances like this all over:

1

drawn.append(card)
_on_cards_changed()

2

drawn.clear()
_on_cards_changed()

3

drawn.pop_back()
_on_cards_changed()

4

drawn.append_array(cards)
_on_cards_changed()

It is annoying having to explicitly call the function whenever drawn’s size changes, and it is easy to forget adding the call. How could I automatically call my function whenever the size of my Array changes?

Could you hook into the setget to the properties that you want to watch?

SteveSmith | 2023-03-06 07:27

The problem I have with setget on drawn is the following:

  1. set wouldn’t work. In the examples above, I don’t set drawn to a new value (e.g. no drawn = newValue), so the set function would not be called.
  2. get would not call the function at the right time. With a call like drawn.pop_back(), the get function would be called immediately before pop_back, which is a bit too early.

Beamer159 | 2023-03-06 07:45

:bust_in_silhouette: Reply From: zhyrin

The interface of Array doesn’t provide a built-in way to do this.
What you could do is write a wrapper class that holds your array, and each function in your wrapper class that would modify the size calls the function with the side-effect.