Skip to content

Commit

Permalink
Merge pull request #177 from dhershman1/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
dhershman1 committed Sep 22, 2024
2 parents a03bd61 + ed6d0f0 commit b3e61a2
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 1 deletion.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## v3.1.0

### New

- Added new `memoizeWith` function
- Added new types for `memoizeWith`
- Added new unit tests for `memoizeWith`

## v3.0.0

### Breaking Changes
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "kyanite",
"version": "3.0.0",
"version": "3.1.0",
"description": "A small library of pure functional utilities to make life easier and data better",
"main": "dist/kyanite.min.cjs",
"type": "module",
Expand Down
32 changes: 32 additions & 0 deletions src/function/memoizeWith.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import _curry2 from '../_internals/_curry2.js'
/**
* @name memoizeWith
* @function
* @since v3.1.0
* @category Function
* @sig (*... -> String) -> function -> function
* @description Wraps a function with a memoization layer to cache the results of the function
* @param {Function} keyFn The function to generate a key to store the results
* @param {Function} fn The function to wrap with memoization
* @return {Function} A new function that will cache the results of the function
* @example
* import { memoizeWith } from 'kyanite'
*
* const add = (a, b) => a + b
* const memoizedAdd = memoizeWith((a, b) => `${a}-${b}`, add)
*
* memoizedAdd(1, 2) // => 3
* memoizedAdd(1, 2) // => 3 (cached)
*/
const memoizeWith = (keyFn, fn) => {
const cache = {}

return (...args) => {
const key = keyFn(...args)
const result = cache[key] = cache[key] || fn(...args)

return result
}
}

export default _curry2(memoizeWith)
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export { default as isEmpty } from './function/isEmpty.js'
export { default as isNil } from './function/isNil.js'
export { default as lt } from './function/lt.js'
export { default as lte } from './function/lte.js'
export { default as memoizeWith } from './function/memoizeWith.js'
export { default as not } from './function/not.js'
export { default as notEq } from './function/notEq.js'
export { default as on } from './function/on.js'
Expand Down
120 changes: 120 additions & 0 deletions tests/function/memoizeWith.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import test from 'tape'
import memoizeWith from '../../src/function/memoizeWith.js'

test('memoizeWith - basic functionality', (t) => {
const add = (a, b) => a + b
const memoizedAdd = memoizeWith((a, b) => `${a}-${b}`, add)

t.equal(memoizedAdd(1, 2), 3, '1 + 2 should equal 3')
t.equal(memoizedAdd(1, 2), 3, '1 + 2 should equal 3 (cached)')
t.equal(memoizedAdd(2, 3), 5, '2 + 3 should equal 5')
t.equal(memoizedAdd(2, 3), 5, '2 + 3 should equal 5 (cached)')

t.end()
})

test('memoizeWith - cache functionality', (t) => {
let callCount = 0
const add = (a, b) => {
callCount++
return a + b
}
const memoizedAdd = memoizeWith((a, b) => `${a}-${b}`, add)

memoizedAdd(1, 2)
memoizedAdd(1, 2)
memoizedAdd(2, 3)
memoizedAdd(2, 3)

t.equal(callCount, 2, 'Function should be called twice due to caching')

t.end()
})

test('memoizeWith - is curried', t => {
let callCount = 0
const add = (a, b) => {
callCount++
return a + b
}
const memoizedAdd = memoizeWith((a, b) => `${a}-${b}`)(add)

memoizedAdd(1, 2)
memoizedAdd(1, 2)
memoizedAdd(2, 3)
memoizedAdd(2, 3)

t.equal(callCount, 2, 'Function should be called twice due to caching')

t.end()
})

test('memoizeWith - calculates the value for a given input only once', t => {
let callCount = 0
const add = (a, b) => {
callCount++
return a + b
}
const memoizedAdd = memoizeWith((a, b) => `${a}-${b}`, add)

memoizedAdd(1, 2)
memoizedAdd(1, 2)
memoizedAdd(1, 2)
memoizedAdd(1, 2)

t.equal(callCount, 1, 'Function should be called once due to caching')

t.end()
})

test('memoizeWith - handles multiple arguments', t => {
let callCount = 0
const add = (...args) => {
callCount++
return args.reduce((acc, val) => acc + val, 0)
}
const memoizedAdd = memoizeWith((...args) => args.join('-'), add)

memoizedAdd(1, 2, 3)
memoizedAdd(1, 2, 3)
memoizedAdd(1, 2, 3)
memoizedAdd(1, 2, 3)

t.equal(callCount, 1, 'Function should be called once due to caching')

t.end()
})

test('memozieWith - can be applied to a nullary function', t => {
let callCount = 0
const get = () => {
callCount++
return 'value'
}
const memoizedGet = memoizeWith(() => 'key', get)

t.equal(memoizedGet(), 'value', 'Function should return the correct value')
t.equal(memoizedGet(), 'value', 'Function should return the correct value')
t.equal(memoizedGet(), 'value', 'Function should return the correct value')
t.equal(callCount, 1, 'Function should be called once due to caching')

t.end()
})

test('memoizeWith - can be applied to a function with optional arguments', t => {
let callCount = 0
const add = (a, b = 0) => {
callCount++
return a + b
}
const memoizedAdd = memoizeWith((a, b) => `${a}-${b}`, add)

memoizedAdd(1)
memoizedAdd(1)
memoizedAdd(1, 2)
memoizedAdd(1, 2)

t.equal(callCount, 2, 'Function should be called twice due to caching')

t.end()
})
9 changes: 9 additions & 0 deletions types/index.d.cts
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,15 @@ declare namespace K {
*/
median(list: ReadonlyArray<number>): number;

/**
* Wraps a function with a memoization layer to cache the results of the function
*/
memoizeWith<T extends (...args: readonly any[]) => any>(
keyFn: (...v: Parameters<T>) => string,
fn: T
): T;


/**
* Goes through an array of values and grabs the min value of the array
*/
Expand Down
8 changes: 8 additions & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,14 @@ declare namespace K {
*/
median(list: ReadonlyArray<number>): number;

/**
* Wraps a function with a memoization layer to cache the results of the function
*/
memoizeWith<T extends (...args: readonly any[]) => any>(
keyFn: (...v: Parameters<T>) => string,
fn: T
): T;

/**
* Goes through an array of values and grabs the min value of the array
*/
Expand Down

0 comments on commit b3e61a2

Please sign in to comment.