Functions that I find useful

I was looking through the Bulletin Board and I came across this post
Table.filter function - Bulletin Board - Developer Forum | Roblox

But it is kind of messy so I made it a little bit better (It also has typechecking)

-- Filters a table based on a predicate function.
local function filter<K, V>(table : {[K]: V}, callback : (K, V) -> boolean) : {[K]: V}
	local result = {}
	
	for i, v in table do
		if callback(i, v) then
			result[i] = v
		end
	end
	
	return result
end

And also the compare function

local function compare(x, ...)
	return table.find({...}, x) ~= nil
end

It just simplifies your if statements so instead of doing this

if foo == bar and foo == baz and foo == qux then
    -- ...
end

You can do this

if compare(foo, bar, baz, qux) then
    -- ...
end

I know this isn’t a lot but I thought it would be helpful for some people so there you go

10 Likes

Creating an array just for comparisons then doing a table.find call doesn’t seem quite fast though, in alot of cases doing it the traditional way would be miles faster… And for filter, just don’t put in incorrect elements in the first place. But if your code doesn’t need to be fast and maybe you like js, this is a pretty solid post.

Heres a function I’d like to add which I use quite alot:

local function jumpTable<T..., R...>(cases: {[any | "_"]: (T...) -> (R...)}) -> (caseItem: any, T...) -> (R...)
     return function(case, ...) 
         local handler = cases[case]
         if handler then return handler(...) end
         local default = cases._
         if not default then return end
         return default(...) -- Default case
     end
end

It is essentially a switch statement; you can do this:

local jump = jumpTable {
    Monday = function() print("It Is Monday") end,
    Tuesday = function() print("It Is Tuesday") end,
    _ = function() warn("Unknown day") end
}

jump("Monday")
jump("Saturday") -- Unknown day

It is quite nice for places where you have alot of possible values for something, makes it faster but also reduces overall nesting

3 Likes

Can’t you just do

foo[“bar”](…)
2 Likes

Yes, but this automatically handles default cases for you :slight_smile:

1 Like

So basically (foo["bar"] or foo._default)(...) ?

When you do that alot it does get kinda annoying :frowning:

So?

local function switch(case, key, ...)
	return (case[key] or case._default)(...)
end
3 Likes

Or if you wanna get really fancy you can also use metatables to do this:

local t = setmetatable({
		Monday = function ()
			print("I hate mondays")
		end,
		_default = function ()
			print("I hate unknown days")
		end,
	},
	{
		__index = function (t, k)
			return rawget(t, k) or rawget(t, "_default")
		end
	}
)


t["Monday"]() --> I hate mondays
t["Tuesday"]() --> I hate unknown days
1 Like

just use cryo, it’s incredibly convenient when you need… It’s incredibly convenient at all times.

1 Like

If you don’t mind me asking, what is that exactly?

Just seems unnecessarily complicated?

1 Like

Cryo is a library that provides a set of utilities for working with tables, treating them as dictionaries and lists (key-value or dictionary-like like tables and index-value or list-like tables)

-- with cryo
local Cryo = require(script.Cryo)

local players = {
	{ name = "Alice", score = 100 },
	{ name = "Bob", score = 50 },
	{ name = "Charlie", score = 150 }
}

local highScorers = Cryo.List.map(
	Cryo.List.filter(players, function(player) return player.score > 75 end),
	function(player) return player.name end
)

print(highScorers)
-- Yo, this is so reaable!


-- no cryo:
local players = {
  { name = "Alice", score = 100 },
  { name = "Bob", score = 50 },
  { name = "Charlie", score = 150 }
}

local highScorers = {}
for _, player in ipairs(players) do
  if player.score > 75 then
    table.insert(highScorers, player.name)
  end
end

print(highScorers)
--Oh no! So ugly!!

btw Im also recomend use Symbol.
because Symbol(“F”) == Symbol(“F”) is false, you can do something like pseudo private

local Symbol = require(script.Symbol)

local function tryToAddPrivate(o)
	local symbolKey = Symbol.for_('Hi')
	o[symbolKey] = 42
end

local obj = { prop = 'hello' }
tryToAddPrivate(obj)

print( obj[Symbol.for_('Hi')] ) -- 42
print( obj.Hi ) -- nil
2 Likes

Ipairs detected


for me the no cryo is infinitely more understandable but whatever

Yes, ipairs is cringe. Its was written(or writed? Idk, Im bad in English, sorry) by chat gpt for example

you dont need a library for symbols you can just do local symbolKey = newproxy()

There is a difference. And, I think, creating a “new symbol” sounds much better, rather than “I created my own user data”.
It pisses me off when people say the obvious things like no one understands.:unamused:

When you understand how to use it, it’s really much more convenient.

what could the difference possibly be, also, you dont have to say “i created my own user data” you can just call it a symbol? what sounds so much worse for me is having to require a module every single time i have to create a symbol-like data structure, like okay if you dont wanna fw userdata then just do local symbolKey = {} it does the same thing

1 Like

I may be damn stupid, but what is the purpose of it?
table.sort does the exact same thing to me?
If you want to remove something entirely, you can just do table.remove() which will be 99999 times more optimized, and you will be able to come back to the code and say, “Oh yeah, I understand what it does.”
without abstracting already quadrillion times abstracted lua tables
not to mention that anonimous functions is a hell for gc to handle

What’s the point of that?
It’s not Java or C#; it’s Luau.
And on Luau, you should program well in Luau code!
This kind of “abstraction” is doing the opposite of helping and is bloatwaring the code to an unreadable state :man_facepalming: that is also making the code laggy.
Also, you should reference keys directly because indexing them is expensive ( --!optimize 2 doesn’t work on user-defined tables).