Skip to content

Instantly share code, notes, and snippets.

@witchiestwitchery
Last active February 9, 2024 16:58
Show Gist options
  • Save witchiestwitchery/e1581cf1e3b1d8984091d551babd6512 to your computer and use it in GitHub Desktop.
Save witchiestwitchery/e1581cf1e3b1d8984091d551babd6512 to your computer and use it in GitHub Desktop.
Simpler alternatives to signals
--!strict
-- Caller
-- a simple signal alterative, thats a function that returns 2 functions
-- first is for adding a callback and returns a function to disconnect
-- second is for running the callbacks with the given values
-- inspired by bin from util.redblox.dev
-- 09/02/2024
-- @Kalrnlo
export type Caller<A...> = (CallbackStorage: {} | {{Callback<A...>}}) -> (Connector<A...>, Sender<A...>)
export type Connector<A...> = (Callback: Callback<A...>) -> Disconnect
export type Callback<A...> = (A...) -> ()
export type Sender<A...> = (A...) -> ()
export type Disconnect = () -> ()
local function SwapRemove<V>(Table: {V}, Value: V)
local Index = table.find(Table, Value)
if Index then
if #Table > 1 then
Table[Index] = Table[#Table]
Table[#Table] = nil
else
Table[Index] = nil
end
end
end
local function Caller<A...>(CallbackStorage: {} | {{Callback<A...>}})
return function(Callback: Callback<A...>)
local CallbackData = table.create(1, Callback)
table.insert(CallbackStorage, CallbackData)
return function()
SwapRemove(CallbackStorage, CallbackData)
end
end, function(...: A...)
for _, CallbackData in CallbackStorage :: {{Callback<A...>}} do
task.spawn(CallbackData[1], ...)
end
end
end
return Caller
export type Callback<A...> = (A...) -> ()
export type Caller<A...> = {
Add: (self: Caller<A...>, Callback: Callback<A...>) -> (() -> ()),
Run: (self: Caller<A...>, ...: A...) -> (),
Destroy: (self: Caller<A...>) -> (),
CallbackList: {{Callback<A...>}}
}
local function Add<A...>(self: Caller<A...>, Callback: Callback<A...>)
local CallbackData = table.create(1, Callback)
table.insert(self.CallbackList, CallbackData)
return function()
local Index = table.find(self.CallbackList, CallbackData)
if Index then
table.remove(self.CallbackList, Index)
end
end
end
local function Run<A...>(self: Caller<A...>, ...: A...)
for _, CallbackData in self.CallbackList do
task.spawn(CallbackData[1], ...)
end
end
local function Destroy<A...>(self: Caller<A...>)
table.clear(self.CallbackList)
end
local function CallerCreator<A...>()
return ({
CallbackList = {},
Destroy = Destroy,
Run = Run,
Add = Add,
} :: any) :: Caller<A...>
end
return CallerCreator
local Caller = require(Path.To.Caller)
local Storage = {}
local Add, Run = Caller(Storage)
Add(function(Name: string, DoesLikeBlueberries: boolean)
if DoesLikeBlueberries then
print(`{Name} likes blueberries!`)
else
print(`{Name} hates blueberries! and now the blueberry farmers hate {Name}!!!`)
end
end)
Run("Lynn", true) -- Lynn likes blueberries!
-- to remove all callbacks just clear the storage table!
table.clear(Storage)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment