Using some kind of id to reference each array and having helper functions to access or manipulate them is probably the easiest way to go. Uid is good as an id since you can access newly created instances immediately. Iid is an alternate idea where you can access data without a helper function. For ex: array(a).at(5). But for iid you’d not want to be creating instances on the fly, instead you’d want an object pool that you’d allocate from.
Global, static or instance variables would require you to create arrays. And for instance variables you’d need to manually destroy them.
For local variables you could either manually destroy them when done with them (tedious to keep track of) or just mark them as temporary and then clean up all the temporary instances at the end of the tick. Still it will be on you to make sure you don’t store temporary arrays in non local places.
Another strategy for locals is to just have a small amount that you juggle the use of. Typically you don’t need too many.
You mentioned json. You could use a single json object to store all the arrays instead instances of the array object. I say a single instance because that could be simpler to work with than dealing with picking.
If you use helper functions to access stuff you can implement things anyway you like under the hood. Here’s a possible design of the helper function.
new(tempBool) -> id
delete(id)
isTemp(id) -> true/false
clone(id) -> newId
copy(id, other)
equals(id1, id2) -> true/false
clearToValue(id, value)
mergeX(id, otherId)
mergeY(id, otherId)
getwidth(id) -> width
getheight(id) -> height
setSize(id, width, height)
get(id, x, y) -> value
set(id, x, y, value)
Anyways. Just some ideas. I’ll have a look at an implementation later. There are usually simplifications that can be done.