mirror of
https://github.com/littensy/charm.git
synced 2026-10-21 11:44:08 +00:00
perf: call mapper as-is in mapped()
This commit is contained in:
parent
27c7f5a6fd
commit
c52f55a55e
2 changed files with 42 additions and 53 deletions
|
|
@ -914,22 +914,9 @@ end
|
|||
@see https://github.com/littensy/charm?tab=readme-ov-file#mappedgetter-mapper
|
||||
]]
|
||||
local function mapped<KI, VI, KO, VO>(getter: Getter<{ [KI]: VI }>, mapper: (VI, KI) -> (VO, KO)): Getter<{ [KO]: VO }>
|
||||
local map = noYield(mapper)
|
||||
local nextInput: { [KI]: VI } = {}
|
||||
local keyMap: { [KI]: KO } = {}
|
||||
|
||||
local function mapUntracked(value: VI, key: KI): (VO, KO)
|
||||
local prevSub = setActiveSub(nil)
|
||||
local success, valueOut, keyOut = pcall(map, value, key)
|
||||
activeSub = prevSub
|
||||
|
||||
if not success then
|
||||
error(`mapped() transform function failed: {valueOut}`, 0)
|
||||
end
|
||||
|
||||
return valueOut, if keyOut == nil then key :: any else keyOut
|
||||
end
|
||||
|
||||
return computed(function(lastOutput: { [KO]: VO }?): { [KO]: VO }
|
||||
local nextOutput: { [KO]: VO } = lastOutput or {}
|
||||
local prevInput = nextInput
|
||||
|
|
@ -937,19 +924,19 @@ local function mapped<KI, VI, KO, VO>(getter: Getter<{ [KI]: VI }>, mapper: (VI,
|
|||
|
||||
-- For keys that were removed from the input, remove the corresponding
|
||||
-- keys from the output.
|
||||
for prevKeyIn in prevInput do
|
||||
if nextInput[prevKeyIn] ~= nil then
|
||||
for keyIn in prevInput do
|
||||
if nextInput[keyIn] ~= nil then
|
||||
continue
|
||||
end
|
||||
|
||||
local prevKeyOut = keyMap[prevKeyIn]
|
||||
local keyOut = keyMap[keyIn]
|
||||
|
||||
if prevKeyOut ~= nil then
|
||||
if keyOut ~= nil then
|
||||
if nextOutput == lastOutput then
|
||||
nextOutput = table.clone(nextOutput)
|
||||
end
|
||||
nextOutput[prevKeyOut] = nil
|
||||
keyMap[prevKeyIn] = nil
|
||||
nextOutput[keyOut] = nil
|
||||
keyMap[keyIn] = nil
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -957,13 +944,14 @@ local function mapped<KI, VI, KO, VO>(getter: Getter<{ [KI]: VI }>, mapper: (VI,
|
|||
-- the output. If the mapper returns a new key that is different from
|
||||
-- the previous call, the old mapped key should be removed from the
|
||||
-- output.
|
||||
for nextKeyIn, nextValueIn in nextInput do
|
||||
if nextValueIn == prevInput[nextKeyIn] then
|
||||
for keyIn, nextValueIn in nextInput do
|
||||
if nextValueIn == prevInput[keyIn] then
|
||||
continue
|
||||
end
|
||||
|
||||
local nextValueOut, nextKeyOut = mapUntracked(nextValueIn, nextKeyIn)
|
||||
local prevKeyOut = keyMap[nextKeyIn]
|
||||
local nextValueOut, keyOutOrNil = mapper(nextValueIn, keyIn)
|
||||
local nextKeyOut: KO = if keyOutOrNil ~= nil then keyOutOrNil else keyIn :: any
|
||||
local prevKeyOut = keyMap[keyIn]
|
||||
|
||||
if prevKeyOut ~= nil and prevKeyOut ~= nextKeyOut then
|
||||
if nextOutput == lastOutput then
|
||||
|
|
@ -971,13 +959,13 @@ local function mapped<KI, VI, KO, VO>(getter: Getter<{ [KI]: VI }>, mapper: (VI,
|
|||
end
|
||||
nextOutput[prevKeyOut] = nil
|
||||
nextOutput[nextKeyOut] = nextValueOut
|
||||
keyMap[nextKeyIn] = nextKeyOut
|
||||
keyMap[keyIn] = nextKeyOut
|
||||
elseif nextOutput[nextKeyOut] ~= nextValueOut then
|
||||
if nextOutput == lastOutput then
|
||||
nextOutput = table.clone(nextOutput)
|
||||
end
|
||||
nextOutput[nextKeyOut] = nextValueOut
|
||||
keyMap[nextKeyIn] = nextKeyOut
|
||||
keyMap[keyIn] = nextKeyOut
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue