Duplicating table values using {...[table]}

As a Roblox developer, it is currently very hard to copy dictionaries/arrays. You either have to create a function to do it for you, or just re-use the same dictionaries. This becomes especially annoying when trying to handle states using something like Rodux.

Rodux is similar to Redux, it allows for quite nice state handling, but it becomes quite tedious to do something like this for each action type:

return {
	EquippedShip = state.EquippedShip;
	SelectedShip = state.SelectedShip;
	ShipSelection = state.ShipSelection;
	ShipSelectionVisible = action.payload;
}

And it gets even worse when you have to do this for each and every action type. Now, don’t get me wrong, Rodux is nice and you could create a function to handle this for you. That being said, it would be nice if Roblox could implement something like this:

return {
	...state;
	ShipSelectionVisible = action.payload;
}

That is to say, it would be nice if we could copy dictionary using {...Dictionary}, and then altering them by having anything after the ...Dictionary be an edit to the table, similar to Dictionary[key] = value. Not only would this be nice for making Rodux more similar to Redux (the main reason I would like to have this added), but it would also allow for easy duplication/editing of duplicated of dictionaries.

This also applies to Arrays. While we can copy arrays using:

local Array2 = unpack({Array1})

It would be nice if this feature could also be implemented for arrays to universalize tables. That is to say, so that both arrays and dictionaries can be copied in a similar way.

Also, according to @sjr04,

Thus, this could be an improvement for copying arrays as well as dictionaries.

All use cases:

  1. Creating a new table with edited values (useful for state management and other things):
local TableEdited = {...Table, ["EditedKey"] = 1}
  1. Copying tables:
local TableCopy = {...Table}
  1. Merging multiple tables into 1 copy:
local Table123 = {...Table1, ...Table2, ...Table3}
  1. A combination of [1] and [3]:
local TableCombination = {...Table1, ...Table2, ...Table3, ["EditedKey"] = 1}
7 Likes

This should suffice for your needs

I’m not entirely sure why this use case would need an official feature to support it.

2 Likes

Other languages do this and it improves code readability and makes copying dictionaries easier in general. This also allows for the copying of multiple dictionaries into one by doing:

{...Dictionary1, ...Dictionary2, ...Dictionary3}

That being said, the initial use case was an example use case, and could be solved by editing the Rodux source code.

What about arrays? The “spread” syntax is used on arrays as well in javascript.

You could implement a union method to do this for you very easily. I’m not sure that any special syntax is warranted, and arguably it’s more confusing.

local function union(...)
  local r = {}
  for i = 1, select("#", ...) do
    for k, v in pairs(select(i, ...) do
      r[k] = v
    end
  end
  return r
end

You could then use it to achieve similar results:

return union(state, {
  ShipSelectionVisible = action.payload;
})

Currently you can easily copy arrays using {unpack(Array), unpack(Array2)}, so I didn’t think it necessary. That being said, it could also be relevant if the one for dictionaries were to be implemented.

This is true, however with how reducers would be setup, you would need to import (or require) this function in every script that creates a reducer. That being said, it is definitely possible to edit the source code to achieve the same result while just returning a dictionary that contains changes, and merging the two while giving the returned one overwrite priority… Either way though, this would be a nice feature to have.

Additionally, I don’t see how the ...Dictionary idea is confusing for duplicating dictionary values. For instance, javascript implements this and it is very nice/clean.

unpack has a limit, and that doesn’t work. unpack(Array) only evaluates to the first expression since it isn’t the last one in the expression list. So I think it should support arrays as well.

I would also like to add I am not necessarily supporting the request but if it were to be added it should at the very least support arrays as well

Interesting, I will edit the topic to include this for arrays as well.

You’re already requiring many different components, as well as Rodux. I don’t find requiring another module an overly compelling argument :sweat_smile:

Personally, I don’t view JavaScript as a language to take inspiration from. There are so many gotchas and things that aren’t completely obvious when working in the language. Having three dots unnecessarily complicates something which is far more explicit as a method.

One concern I would have with this syntax is removing values from tables. Even my method doesn’t support this due to the nature of nil.

While this would normally be the case, the way that I implement state in specific places does not actually require you to require Rodux in that module, instead it returns an array containing Reducers and Subscriptions (.changed event binds), that gets required by a handler module. This handler module creates stores and re-routes dispatches to events based on action.type and an additional value action.key.

Also, I do agree that this is far more explicit as a method, but it is still very easy to learn how to implement {...Dictionary1; key = value}, and it is alot simpler to implement as a developer.

How would you find the difference between ‘arrays’ and ‘dictionaries’?

Also shouldn’t this work with expressions rather than just variables, so {…[exp]} instead of {…[name]}?

What would happen when multiple of the table define the same field in the table?


Lua doesn’t have anything like this because there are lots of different ways to copy tables, maybe arrays should be appended or maybe it should add values from the table until it reaches the length.

There are also a few cases which seems to be odd to disambiguate

local x = {... .. ...} -- valid
local y = {...-...} -- valid, could be interpreted using the new system

Arrays and dictionaries are stored differently. This is what causes the mixed-table error when you try to combine both. The engine can easily differentiate between the two since they are not at all the same.

It should only take a Dictionary value in the case of a dictionary, and it should only take an Array value in the case of an Array. Any reference to an array or dictionary should be taken after the ...

Not sure what you mean here, but if you mean, say:

local Dictionary1 = {["Test"] = 123; ["Test2"] = 234;};
local Dictionary2 = {["Test2"] = 345; ["Test2"] = 456;};

local Dictionary3 = {...Dictionary1; ...Dictionary2;}

Then Dictionary3 would give priority to the latter one (Dictionary2), as it would write from left to right. Meaning, it would iterate through Dictionary1, set keys/values, then iterate through Dictionary2, and so on.

Not quite sure how these are valid.

Arrays and dictionaries are stored under the same type, table. Having weird semantics around what would make a table an array vs a dictionary doesn’t sound like a good idea; for instance what would happen if the array had holes in it, would it be a dictionary in that case? Also I’m not sure what you mean by mixed-table error, I’m able to use mixed tables just fine.

local tbl = {1,a=2}
print(tbl[1]) --> 1
print(tbl.a) --> 2

I’m not talking about the value type, the title of this feature requests mentions the syntax {...[tableName]}, which seems to imply that it would be the name of a variable. It would seem more logical to have this work with all kinds of expressions, so for instance you could use the result of a function directly instead of saving to a temporary variable and using that.

The first line creates a table with 1 value at index 1 which is the concatenation of the first value of the vararg expression and the first value of the vararg expression. The second line creates a table with 1 value at index 1 which is the subtraction of the first value of the vararg expression and the first value of the vararg expression.

I miss-remembered how mixed tables are handled in lua. This error only applies for storing in a datastore, and possibly transfering over RemoteEvents/RemoteFunctions. The former is accurate, the latter might be. That being said, I don’t see how this would cause an issue regardless, because if Roblox supports mixed-tables, then it should have no problem combining a mixed table with a table. Though, the initial question of “How would you find the difference between ‘arrays’ and ‘dictionaries’?” no longer applies and the idea just broadly applies to tables. I initially thought they needed to be separate, but that does not seem to be the case… though it should.

This is the intention, though I the idea is that it only applies to tables… if that makes sense. But you are correct. I will edit the topic to account for this.

What I should have said is that I don’t understand how this would cause an issue. You can currently do this with tables as is, and this does not apply to this question. ... as a tuple is not the same as this request. How you currently have it, would it not just create an array with a singular value.

They do create arrays with singular values, the subtraction and concatenation operators will always result in one value.

The problem is with how you proposed the syntax

local tbl = {...-...}

Using your proposed syntax this could be copying the table from the result of -...

local temp = -...
local tbl = {...temp}

However it’s currently valid syntax, therefore it would be ambiguous.