import { isArraysEqual } from './array' ; import { isPropsEqual } from './object' ; import { Dictionary } from '../options' ; export function memoize < Args extends any [ ] , Res > ( workerFunc , resEquality ? , teardownFunc ? ) { let currentArgs ; let currentRes ; return function ( ... newArgs ) { if ( ! currentArgs ) { currentRes = workerFunc . apply ( this , newArgs ) ; } else if ( ! isArraysEqual ( currentArgs , newArgs ) ) { if ( teardownFunc ) { teardownFunc ( currentRes ) ; } let res = workerFunc . apply ( this , newArgs ) ; if ( ! resEquality || ! resEquality ( res , currentRes ) ) { currentRes = res ; } } currentArgs = newArgs ; return currentRes ; } ; } export function memoizeObjArg < Arg extends Dictionary , Res > ( workerFunc , resEquality ? , teardownFunc ? ) { let currentArg ; let currentRes ; return ( newArg ) => { if ( ! currentArg ) { currentRes = workerFunc . call ( this , newArg ) ; } else if ( ! isPropsEqual ( currentArg , newArg ) ) { if ( teardownFunc ) { teardownFunc ( currentRes ) ; } let res = workerFunc . call ( this , newArg ) ; if ( ! resEquality || ! resEquality ( res , currentRes ) ) { currentRes = res ; } } currentArg = newArg ; return currentRes ; } ; } export function memoizeArraylike < Args extends any [ ] , Res > ( workerFunc , resEquality ? , teardownFunc ? ) { let currentArgSets = [ ] ; let currentResults = [ ] ; return ( newArgSets ) => { let currentLen = currentArgSets . length ; let newLen = newArgSets . length ; let i = 0 ; for ( ; i < currentLen ; i += 1 ) { if ( ! newArgSets [ i ] ) { if ( teardownFunc ) { teardownFunc ( currentResults [ i ] ) ; } } else if ( ! isArraysEqual ( currentArgSets [ i ] , newArgSets [ i ] ) ) { if ( teardownFunc ) { teardownFunc ( currentResults [ i ] ) ; } let res = workerFunc . apply ( this , newArgSets [ i ] ) ; if ( ! resEquality || ! resEquality ( res , currentResults [ i ] ) ) { currentResults [ i ] = res ; } } } for ( ; i < newLen ; i += 1 ) { currentResults [ i ] = workerFunc . apply ( this , newArgSets [ i ] ) ; } currentArgSets = newArgSets ; currentResults . splice ( newLen ) ; return currentResults ; } ; } export function memoizeHashlike < Args extends any [ ] , Res > ( workerFunc , resEquality ? , teardownFunc ? ) { let currentArgHash = { } ; let currentResHash = { } ; return ( newArgHash ) => { let newResHash = { } ; for ( let key in newArgHash ) { if ( ! currentResHash [ key ] ) { newResHash [ key ] = workerFunc . apply ( this , newArgHash [ key ] ) ; } else if ( ! isArraysEqual ( currentArgHash [ key ] , newArgHash [ key ] ) ) { if ( teardownFunc ) { teardownFunc ( currentResHash [ key ] ) ; } let res = workerFunc . apply ( this , newArgHash [ key ] ) ; newResHash [ key ] = ( resEquality && resEquality ( res , currentResHash [ key ] ) ) ? currentResHash [ key ] : res ; } else { newResHash [ key ] = currentResHash [ key ] ; } } currentArgHash = newArgHash ; currentResHash = newResHash ; return newResHash ; } ; }