refactor!: rename derive, map

This commit is contained in:
Richard 2024-05-26 21:31:28 -07:00
parent f2f7a16599
commit b715b81fec
18 changed files with 163 additions and 133 deletions

53
src/mapped.luau Normal file
View file

@ -0,0 +1,53 @@
local atom = require(script.Parent.atom)
local effect = require(script.Parent.effect)
local peek = require(script.Parent.peek)
local types = require(script.Parent.types)
type Atom<T> = types.Atom<T>
type Molecule<T> = types.Molecule<T>
type Map =
(<K0, V0, K1, V1>(fn: Molecule<{ [K0]: V0 }>, mapper: (V0, K0) -> (V1?, K1)) -> Molecule<{ [K1]: V1 }>)
& (<K0, V0, V1>(fn: Molecule<{ [K0]: V0 }>, mapper: (V0, K0) -> V1?) -> Molecule<{ [K0]: V1 }>)
& (<K0, V0, K1, V1>(fn: Molecule<{ [K0]: V0 }>, mapper: (V0, K0) -> (V1?, K1?)) -> Molecule<{ [K1]: V1 }>)
local function mapped<K0, V0, K1, V1>(molecule: Molecule<{ [K0]: V0 }>, mapper: (V0, K0) -> (V1?, K1?)): Molecule<{ [K1]: V1 }>
local mappedAtom = atom({})
local mappedAtomRef = setmetatable({ current = mappedAtom }, { __mode = "v" })
local prevMappedItems: { [K1]: V1 } = {}
local unsubscribe
unsubscribe = effect(function()
if not mappedAtomRef.current then
return unsubscribe()
end
local items = molecule()
local mappedItems = table.clone(peek(mappedAtomRef.current))
local mappedKeys = {}
for key, item in items do
local newItem, newKey = mapper(item, key)
if newKey == nil then
newKey = key :: any
end
if mappedItems[newKey :: K1] ~= newItem then
mappedItems[newKey :: K1] = newItem :: V1
else
mappedKeys[newKey] = key
end
end
for key in prevMappedItems do
if mappedKeys[key] == nil and mappedItems[key] == prevMappedItems[key] then
mappedItems[key] = nil
end
end
prevMappedItems = mappedItems
mappedAtom(mappedItems)
end)
return mappedAtom
end
return mapped :: Map