Skip to content

Latest commit

 

History

History
133 lines (95 loc) · 3.83 KB

M2A_24.md

File metadata and controls

133 lines (95 loc) · 3.83 KB

M2#A24 - TDD - reduce recursivo

Código normal

'use strict'

const reduce = (arr, func, initialValue) => {
  let acc = initialValue
  let arrCopy = arr

  if(initialValue === undefined) {
    acc = arr[0]
    arrCopy = arr.slice(1)
  }

  for(var i = 0; i < arrCopy.length; i++){
    acc = func(acc, arrCopy[i], i, arrCopy)
  }
  return acc
}

export default reduce

Código recursivo

Comentários do código

const reduce = (arr, func, initialValue) => {
  let acc = initialValue
  let arrCopy = arr

  if(initialValue === undefined) {
    acc = arr[0]
    arrCopy = arr.slice(1)
  }

  return (function reduceInternal (accInternal, arrInternal, counter) { 
    const [head, ...tail] = arrInternal

    return arrInternal.lenghth === 0
      ? accInternal
      : reduceInternal(func(accInternal, head, counter, arrCopy), tail, counter + 1)
  })(acc, arrCopy, 0)
}

return (function reduceInternal (accInternal, arrInternal, counter) { - passando aqui os valores inicias de todos os parametros que serão modificados

const [head, ...tail] = arrInternal - cabeça e cauda que vão pegar no array interno

reduceInternal(func(accInternal, head, counter, arrCopy), tail, counter + 1)- Chamada recursiva da função passando uma função com os seguintes argumentos - acumulador, primeiro item do array, contador, array inicial (copia do array menos o primeiro item) e outros argumentos da função recursiva que são restante do array, contador

})(acc, arrCopy, 0) - acumulador, cópia do array, indice da iteração

Refactoring

Vamos aproveitar também para remover a mutabilidade de código

Aqui estamos removendo a mutabilidade do código que é feita na alteração do valores dentro do IF. O quanto mais deixarmos nosso código não mutável melhor, resolvemos isso criando a constante e já iniciando o nosso método com os valores setados que precisamos.

A função isInitialValueUndefined foi criada fora do método reduce para otimizarmos o nosso código. Se ela fosse criada dentro teriamos uma má performance pelo fato de toda vez que fosse executado o método reduce ela seria criada novamente. Da forma que está nos temos uma refêrencia para a função e não temos também uma concorrência com outras fuções

Antes:

 let acc = initialValue
  let arrCopy = arr

  if(initialValue === undefined) {
    acc = arr[0]
    arrCopy = arr.slice(1)
  }

Depois:

const isInitialValueUndefined = (initialValue) => initialValue === undefined

const reduce = (arr, func, initialValue) => {
  const acc = isInitialValueUndefined(initialValue) ? arr[0] : initialValue
  const arrCopy = isInitialValueUndefined(initialValue) ? arr.slice(1) : arr

Criamos agora uma função accNextpara removermos a chamada que está muito grande no método. Lembre-se que esse método está funcionando por quê está retornando uma função. Caso estivesse sendo só declarada a função dentro da variável seria executada duas vezes o nosso código e o resultado dessa função seria atribuida a essa variável accNext.

Antes:

  return arrInternal.lenghth === 0
    ? accInternal
    : reduceInternal(func(accInternal, head, counter, arrCopy), tail, counter + 1)
})(acc, arrCopy, 0)

Depois:

return (function reduceInternal (accInternal, arrInternal, counter) {
  const [head, ...tail] = arrInternal
  const accNext = () => func(accInternal, head, counter, arrCopy)

  return arrInternal.length === 0
    ? accInternal
    : reduceInternal(accNext, tail, counter + 1)

})(acc, arrCopy, 0)

Testes

'use strict'

const reduce = (arr, func, initialValue) => {
  let acc = initialValue
  let arrCopy = arr

  if(initialValue === undefined) {
    acc = arr[0]
    arrCopy = arr.slice(1)
  }

  for(var i = 0; i < arrCopy.length; i++){
    acc = func(acc, arrCopy[i], i, arrCopy)
  }
  return acc
}

export default reduce