<commit_before>//
// Main
//

module.exports = function memoize (fn, options) {
  const cache = options && options.cache
    ? options.cache
    : cacheDefault

  const serializer = options && options.serializer
    ? options.serializer
    : serializerDefault

  const strategy = options && options.strategy
    ? options.strategy
    : strategyDefault

  return strategy(fn, {
    cache,
    serializer
  })
}

//
// Strategy
//

const isPrimitive = (value) =>
  value == null || (typeof value !== 'function' && typeof value !== 'object')

function strategyDefault (fn, options) {
  function monadic (fn, cache, serializer, arg) {
    const cacheKey = isPrimitive(arg) ? arg : serializer(arg)

    if (!cache.has(cacheKey)) {
      const computedValue = fn.call(this, arg)
      cache.set(cacheKey, computedValue)
      return computedValue
    }

    return cache.get(cacheKey)
  }

  function variadic (fn, cache, serializer, ...args) {
    const cacheKey = serializer(args)

    if (!cache.has(cacheKey)) {
      const computedValue = fn.apply(this, args)
      cache.set(cacheKey, computedValue)
      return computedValue
    }

    return cache.get(cacheKey)
  }

  let memoized = fn.length === 1 ? monadic : variadic<commit_msg>moving `monadic(..)` / `variadic(..)` out of `strategy(..)`<commit_after>//
// Main
//

module.exports = function memoize (fn, options) {
  const cache = options && options.cache
    ? options.cache
    : cacheDefault

  const serializer = options && options.serializer
    ? options.serializer
    : serializerDefault

  const strategy = options && options.strategy
    ? options.strategy
    : strategyDefault

  return strategy(fn, {
    cache,
    serializer
  })
}

//
// Strategy
//

const isPrimitive = (value) =>
  value == null || (typeof value !== 'function' && typeof value !== 'object')

function monadic (fn, cache, serializer, arg) {
  const cacheKey = isPrimitive(arg) ? arg : serializer(arg)

  if (!cache.has(cacheKey)) {
    const computedValue = fn.call(this, arg)
    cache.set(cacheKey, computedValue)
    return computedValue
  }

  return cache.get(cacheKey)
}

function variadic (fn, cache, serializer, ...args) {
  const cacheKey = serializer(args)

  if (!cache.has(cacheKey)) {
    const computedValue = fn.apply(this, args)
    cache.set(cacheKey, computedValue)
    return computedValue
  }

  return cache.get(cacheKey)
}

function strategyDefault (fn, options) {
  let memoized = fn.length === 1 ? monadic : variadic
{'fraction_non_alphanumeric': 0.12842190016103058, 'fraction_numerical': 0.0008051529790660225, 'mean_word_length': 3.1835016835016834, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2915080', 'n_tokens_mistral': 786, 'n_tokens_neox': 758, 'n_words': 194}