Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 61 additions & 13 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,68 @@ function defaultEqualityCheck(a, b) {
return a === b
}

export function defaultMemoize(func, equalityCheck = defaultEqualityCheck) {
let lastArgs = null
let lastResult = null
const isEqualToLastArg = (value, index) => equalityCheck(value, lastArgs[index])
return (...args) => {
if (
lastArgs === null ||
lastArgs.length !== args.length ||
!args.every(isEqualToLastArg)
) {
lastResult = func(...args)
export function defaultMemoize(func, equalityCheck = defaultEqualityCheck, cacheSize=1) {

let cacheArgsArr = [] // Cache store of old argument arrays
let cacheResultArr = [] // Cache store of old results

const memoizedResultFunc = (...args) => {
let foundIdx = -1
const oldCacheResultArr = cacheResultArr
const isFound = cacheArgsArr.some( (oldArgArr,idx)=>{
if( oldArgArr.length !== args.length ) {
return false
}

if( oldArgArr.every( (value,i) => equalityCheck(args[i],value) )) {
foundIdx = idx
}

return foundIdx > -1
})

// console.log( 'foundIdx: ' + foundIdx )
let result
if( isFound ) {
cacheArgsArr = [
args,
...cacheArgsArr.slice( 0, foundIdx ),
...cacheArgsArr.slice( foundIdx+1, cacheSize )
]
cacheResultArr = [
cacheResultArr[foundIdx],
...cacheResultArr.slice( 0, foundIdx ),
...cacheResultArr.slice( foundIdx+1, cacheSize )
]
result = cacheResultArr[0]

} else if( ! isFound ) {

result = func(...args)
cacheArgsArr = [ args, ...cacheArgsArr.slice( 0, cacheSize-1 ) ]
cacheResultArr = [ result, ...cacheResultArr.slice( 0, cacheSize-1 ) ]
result = cacheResultArr[0]
}
lastArgs = args
return lastResult

if( oldCacheResultArr !== cacheResultArr ) {
// console.log( 'updated cache:' )
// console.log( cacheArgsArr )
// console.log( cacheResultArr )
}

return result
}

memoizedResultFunc.getCacheArgsArr = ()=> cacheArgsArr
memoizedResultFunc.getCacheResultArr = ()=> cacheResultArr
memoizedResultFunc.clearCache = ()=> {
cacheArgsArr = []
cacheResultArr = []
}
return memoizedResultFunc
}


function getDependencies(funcs) {
const dependencies = Array.isArray(funcs[0]) ? funcs[0] : funcs

Expand Down Expand Up @@ -59,6 +104,9 @@ export function createSelectorCreator(memoize, ...memoizeOptions) {
selector.resultFunc = resultFunc
selector.recomputations = () => recomputations
selector.resetRecomputations = () => recomputations = 0
selector.getCacheArgsArr = () => memoizedResultFunc.getCacheArgsArr()
selector.getCacheResultArr = () => memoizedResultFunc.getCacheResultArr()
selector.clearCache = () => memoizedResultFunc.clearCache()
return selector
}
}
Expand Down
82 changes: 82 additions & 0 deletions test/test_selector.js
Original file line number Diff line number Diff line change
Expand Up @@ -342,4 +342,86 @@ suite('selector', () => {
)
assert.equal(selector.resultFunc, lastFunction)
})
test('defaultMemoize recomputations with cache size option', () => {

const createSelectorWithCacheSize2 = createSelectorCreator( defaultMemoize, void 0, 2 )

const powerSelector = createSelectorWithCacheSize2([
(state)=>state.num
], ( num )=> num*num )

assert.equal(powerSelector({ num: 1 }), 1) // expect recomputation
assert.equal(powerSelector({ num: 2 }), 4) // expect recomputation
assert.equal(powerSelector({ num: 3 }), 9) // expect recomputation
assert.equal(powerSelector({ num: 4 }), 16) // expect recomputation
assert.equal(powerSelector.recomputations(), 4)

assert.equal(powerSelector.getCacheArgsArr()[0], 4)
assert.equal(powerSelector.getCacheArgsArr()[1], 3)

assert.equal(powerSelector({ num: 4 }), 16) // expect cache
assert.equal(powerSelector({ num: 4 }), 16) // expect cache
assert.equal(powerSelector({ num: 3 }), 9) // expect cache
assert.equal(powerSelector({ num: 3 }), 9) // expect cache
assert.equal(powerSelector({ num: 2 }), 4) // expect recomputation
assert.equal(powerSelector.recomputations(), 5)

assert.equal(powerSelector({ num: 4 }), 16) // expect recomputation
assert.equal(powerSelector({ num: 4 }), 16) // expect cache

assert.equal(powerSelector.recomputations(), 6)
assert.equal(powerSelector.getCacheArgsArr().length, 2 )
})
test('defaultMemoize updatedCache with cache size option', () => {
const createSelectorWithCacheSize5 = createSelectorCreator( defaultMemoize, void 0, 5 )

const powerSelector = createSelectorWithCacheSize5([
(state)=>state.num
], ( num )=> num*num )

assert.equal(powerSelector({ num: 1 }), 1) // expect recomputation
assert.equal(powerSelector({ num: 2 }), 4) // expect recomputation
assert.equal(powerSelector({ num: 3 }), 9) // expect recomputation
assert.equal(powerSelector({ num: 4 }), 16) // expect recomputation
assert.equal(powerSelector({ num: 5 }), 25) // expect recomputation

assert.equal(powerSelector.getCacheArgsArr()[0], 5)
assert.equal(powerSelector.getCacheArgsArr()[1], 4)
assert.equal(powerSelector.getCacheArgsArr()[2], 3)
assert.equal(powerSelector.getCacheArgsArr()[3], 2)
assert.equal(powerSelector.getCacheArgsArr()[4], 1)

assert.equal(powerSelector({ num: 2 }), 4) // expect cache
assert.equal(powerSelector.getCacheArgsArr()[0], 2)
assert.equal(powerSelector.getCacheArgsArr()[1], 5)
assert.equal(powerSelector.getCacheArgsArr()[2], 4)
assert.equal(powerSelector.getCacheArgsArr()[3], 3)
assert.equal(powerSelector.getCacheArgsArr()[4], 1)

assert.equal(powerSelector({ num: 6 }), 36) // expect recomputation
assert.equal(powerSelector.getCacheArgsArr()[0], 6)
assert.equal(powerSelector.getCacheArgsArr()[1], 2)
assert.equal(powerSelector.getCacheArgsArr()[2], 5)
assert.equal(powerSelector.getCacheArgsArr()[3], 4)
assert.equal(powerSelector.getCacheArgsArr()[4], 3)
assert.equal(powerSelector.getCacheArgsArr()[5], void 0)

assert.equal(powerSelector({ num: 1 }), 1) // expect recomputation
assert.equal(powerSelector.getCacheArgsArr()[0], 1)
assert.equal(powerSelector.getCacheArgsArr()[1], 6)
assert.equal(powerSelector.getCacheArgsArr()[2], 2)
assert.equal(powerSelector.getCacheArgsArr()[3], 5)
assert.equal(powerSelector.getCacheArgsArr()[4], 4)
assert.equal(powerSelector.getCacheArgsArr()[5], void 0)

assert.equal(powerSelector({ num: 1 }), 1) // expect cache
assert.equal(powerSelector.getCacheArgsArr()[0], 1)
assert.equal(powerSelector.getCacheArgsArr()[1], 6)
assert.equal(powerSelector.getCacheArgsArr()[2], 2)
assert.equal(powerSelector.getCacheArgsArr()[3], 5)
assert.equal(powerSelector.getCacheArgsArr()[4], 4)
assert.equal(powerSelector.getCacheArgsArr()[5], void 0)

assert.equal(powerSelector.recomputations(), 7)
})
})