It's too hard to get the keys or values of a dictionary

As a Roblox developer, it is currently too hard to get a list of a dictionary’s keys or a list of a dictionary’s values.

I do these two things very frequently for a few purposes:

  • Getting the number of items in the dictionary
  • Selecting a random item in the dictionary
  • Generating a sort order for the items in the dictionary
  • Passing a dictionary’s keys or a dictionary’s values along to another function that expects an array

This appears to be a commonly used pattern by others as well, based on its inclusion in libraries such as Llama, luau-polyfill, and a few other table libraries listed in community resources.

I can get this info manually with only a few lines of code, but it’s still annoying to either write it out every time I use it, or create a module, write the function out in there, and then require the module in every script that uses it. I believe the frequency of this pattern makes it deserving of its own utility functions (table.keys(t) and table.values(t), probably.)

If Roblox is able to address this issue, it would improve my development experience because I would be able to work faster and simplify my code.

7 Likes

It would be nice if they overloaded the # to get the number of keys in a dictionary similar to getting the length of a string or table.

1 Like

All of the purposes you’ve mentioned would be better off using normal arrays.

Their inclusion in common libraries is naive because the need for them is indictive of a more serious design issue (the polyfills aren’t even meant to be used directly, they’re just for TypeScript transpilation needs).

That would be a breaking change.

local Table = {1, 2, A = 3, B = 4}
print(#Table) -- 2
1 Like

Breaking change or not, it’s jarring to see how Lua tables differ from Arrays, lists, and Dictionaries in other languages. Though, f this is an issue I would alternatively recommend more strongly typed data type alternatives for tables. Perhaps introducing Array, Dictionary, and List classes aside from the general table data type. You would then be able to use these classes like their counterparts in other programming languages, just with Luau stylizating.

I may make a feature request on this as it is something that would benefit developers switching to Roblox from other engines.

3 Likes

All of the purposes apply to situations where I am required to use a dictionary due to interactions with other systems, performance, and code clarity.

4 Likes

As much as I’d like table.keys and table.values i feel like it’s kinda pointless but then again they added math.lerp so anythings possible now

local table = setmetatable({
	keys = function(tbl : {[any] : any})
		assert(type(tbl) == "table", `invalid argument #1 to 'keys' (table expected, got {typeof(tbl)})`)
		local Keys = {}
		
		for i in next, tbl do
			table.insert(Keys, i)
		end
		
		return Keys
	end,
	values = function(tbl : {[any] : any})
		assert(type(tbl) == "table", `invalid argument #1 to 'values' (table expected, got {typeof(tbl)})`)
		local Values = {}

		for _, v in next, tbl do
			table.insert(Values, v)
		end

		return Values
	end,
	size = function(tbl : {[any] : any})
		assert(type(tbl) == "table", `invalid argument #1 to 'size' (table expected, got {typeof(tbl)})`)
		local Size = 0
		local idx = next(tbl)
		
		while idx ~= nil do
			Size += 1
			idx = next(tbl, idx)
		end
		
		return Size
	end,
}, {__index = table})

local example = table.create(10, "foo")

table.keys(example) --> {number}
table.values(example) --> {"foo"}
table.size(example) --> 10
1 Like

Since this would go into Luau’s standard library, you could get away with opening an RFC for it.

It’s a bit more involved, but it’ll probably have a faster response time than the devforums.

We are working on improvements for sharing and reusing modules with helper functions.

Having community-built modules is something that is perfectly fine in every programming language and unblocks people from having to wait a long time for each specific function as well as keeping the core language small and maintainable.

3 Likes

I’ll look into this. I’ve made a ton of commits to the creator docs, so hopefully some of that experience will transfer.

They’re different skillsets I think. With RFCs, you have to think about the details a lot more than with documentation. As an example, what is the actual benefit of adding a function? If it’s just ‘convenience’ it had better be pretty darn convenient.

I’ve talked myself out of a bunch of features by going to write RFCs for them. Sometimes that’s how it goes.

I think the benefit of adding more strongly typed alternatives to Lua tables would be a couple of things. On a base level, I would assume that this would introduce specific data types for dictionaries, arrays, and lists that leverage their specific advantages over a transmutable weakly typed data type like tables. There are a number of benefits that strongly typed languages have, increasing what many would just boil down into “performance.”

I think more generally it would be better to support the introduction of types like this to Luau as allowing the implementation of specific features for each data type rather than needing to keep things simple so they don’t interfere with other use cases of a flexible data type like tables. A big upside to the Lua language is its simplicity with native data types, but as Roblox evolves, I think we need to expand upon this while also maintaining support for these native weak data types.

Another thing I would like to mention is that this would improve onboarding for Luau and the Roblox engine. Many developers, specifically programmers, are used to similar data types. Even in weakly typed languages like Python, JavaScript, and C#, the built-in modules and data types for these equivalents are A LOT more strongly typed than Lua tables, which can lead to some confusion in what features they actually have and what’s missing.