Aguarde...

23 de outubro de 2021

Introdução ao Currying em JavaScript

Introdução ao Currying em JavaScript

Currying é uma das técnicas mais avançadas de trabalho com funções. O que ele faz é permitir que você transforme funções e a maneira como você trabalha com elas. Este tutorial ajudará você a entender o que é currying em JavaScript, como funciona e como usá-lo em seu código.

O que é currying

Em primeiro lugar, o currying existe em várias linguagens, não apenas em JavaScript. Provavelmente, existem várias maneiras de explicar o que é currying. Alguns simples? Vamos começar com isso. Currying é um processo. É um processo de transformação de funções com um número específico de argumentos em uma sequência de funções aninhadas.

Cada uma dessas funções na sequência está sendo retornada e cada uma recebe apenas um dos argumentos. Apenas a última função na sequência recebe todos os argumentos espalhados pela sequência, executa alguma operação e retorna um valor ou valores. Esta é a primeira transformação.

// Curried function example:
function curriedFn(a) {
  return function(b) {
    return function(c) {
      return a + b + c
    }
  }
}

// Normal function:
function fn(a, b, c) {
  return a + b + c
}

A segunda transformação é como você chama ou invoca a função curried. Normalmente, você passaria todos os argumentos necessários dentro de um conjunto de parênteses. Não com funções de curry. Ao trabalhar com funções curried, você passa cada argumento em um conjunto separado de parênteses.

// Calling curried function declared above:
curriedFn(11)(22)(33)
// Output:
// 66

// Calling normal function:
fn(11, 22, 33)

Como funciona o currying

Currying pode parecer algo incomum, especialmente para iniciantes. Vamos dar uma olhada em como o currying em JavaScript funciona e por que ele pode até funcionar.

A coisa sobre valores, argumentos e fechamentos

O quão fácil ou difícil é entender currying em JavaScript pode muito bem depender de quão familiarizado você está com o conceito de encerramentos . É graças a obras de currying de fechamentos. Aqui está como esses dois funcionam juntos. Como você pode ver no exemplo, cada função na sequência funciona apenas com um único argumento.

Faria sentido que, quando cada função fosse chamada, o valor passado para ela como um argumento também fosse perdido. Este não é o caso. O valor ainda existe no escopo da função que foi chamada. O que é mais importante é que qualquer função dentro desse escopo também pode acessar esse valor com escopo .

Todos esses valores existem e são acessíveis, enquanto a execução da sequência estiver em andamento. Quando termina com a última função e o valor que retorna, esses valores existentes também desaparecem. É também por isso que a última função mais interna pode operar com todos os argumentos vistos anteriormente.

No caso desta última função na sequência, a mais interna, todos esses valores ainda existem. É também por isso que pode funcionar com eles.

function curriedFn(a) {
  // Argument "a" exists here
  return function(b) {
    // Argument "a" and "b" exist here
    return function(c) {
      // Argument "a", "b" and "c" exist here
      return a + b + c
    }
  }
}

A coisa sobre parênteses

Portanto, a função mais interna pode retornar todos os valores vistos anteriormente porque eles são mantidos vivos graças ao fechamento. E quanto a esses parênteses adicionais? Esses parênteses têm dois propósitos principais. Primeiro, eles permitem passar um argumento específico para uma função específica.

Isso é determinado pela ordem em que os argumentos são definidos na função curried. A segunda coisa é mais importante e interessante. Cada um desses parênteses adicionais é, na verdade, uma nova chamada de função. Isso significa que quando você vê uma função curried com três pares de parênteses, está vendo três chamadas de função.

Cada uma dessas chamadas invoca uma das funções na sequência, ao mesmo tempo que fornece o argumento necessário para essa função.

// Create curried function:
function curriedFn(a) {
  return function(b) {
    return function(c) {
      return a + b + c
    }
  }
}

// Calling curried function:
curriedFn(11)(22)(33)

// can be visualized as:
outermostFn(11) // curriedFn(a) { ... }
middleFn(22) // function(b) { ... }
innermostFn(33) // function(c) { ... }

É também por isso que o currying permite chamar cada função “manualmente”. Cada chamada retorna uma função. O que você pode fazer é pegar cada chamada de função e atribuir sequencialmente seu valor retornado a uma variável. Cada uma dessas etapas resultará em uma variável atribuída a uma função, exceto a última.

A última variável receberá o valor retornado pela última função. Este último valor é o que você obtém quando chama a função curried com todos os argumentos necessários e par de parênteses. A única diferença são essas linhas extras e variáveis ​​atribuídas.

// Create curried function:
function curriedFn(a) {
  return function(b) {
    return function(c) {
      return a + b + c
    }
  }
}

// This:
curriedFn(11)(22)(33)

// is the same as (except those extra lines):
const firstCall = curriedFn(11)
const secondCall = firstCall(22)
const lastCall = secondCall(33)

console.log(firstCall)
// Output:
// ƒ ()
// That is:
// function(b) {
//   return function(c) {
//     return a + b + c
//   }
// }

console.log(secondCall)
// Output:
// ƒ ()
// That is:
// function(c) {
//   return a + b + c
// }

console.log(lastCall)
// Output:
// 66
// That is:
// a + b + c

Funções curried sem argumentos

O currying é geralmente usado para funções definidas com alguns parâmetros. No entanto, esta não é uma regra. Você também pode criar uma função curried que não receba nenhum argumento. Neste caso, você ainda deve fornecer o número correto de parênteses, apenas vazio.

// Create curried function:
function curriedFn() {
  return function() {
    return function() {
      return function() {
        return function() {
          return '??'
        }
      }
    }
  }
}

// Call curriedFn():
curriedFn()()()()()
// Output:
// '??'

Currying arrow functions

Assim como você pode curry funções regulares, você também pode curry funções de seta . Isso pode ajudá-lo a reduzir a quantidade de código que, de outra forma, você teria que usar. Os princípios e a forma de usá-lo ainda são os mesmos. Apenas a sintaxe é diferente, devido à natureza das funções das setas.

// Regular curried function:
function curriedFn(a) {
  return function(b) {
    return function(c) {
      return a + b + c
    }
  }
}

// Arrow function alternative:
const curriedFn = (a) => (b) => (c) => a + b + c

// Calling the curried function:
curriedFn(11)(33)(55)
// Output:
// 99

Funções parciais do aplicativo

Quando falamos sobre currying em JavaScript, também é útil mencionar uma técnica chamada de aplicação parcial. A razão é que esses dois são muito semelhantes, tão semelhantes que pode ser confuso. No entanto, há uma diferença fundamental que o ajudará a distingui-los.

Essa diferença está no número de parâmetros. Quando você curry uma função, cada função na sequência aceita apenas um parâmetro. Este não é o caso da aplicação parcial. No caso de aplicação parcial, a regra é que as funções recém-retornadas devem aceitar menos parâmetros.

Isso significa que ainda pode haver argumentos espalhados por vários pares de parênteses. No entanto, alguns desses pares de parênteses conterão mais do que apenas um argumento. Quando você vê algo assim, está olhando para uma função de aplicativo parcial, não para uma função curried.

// Curried function example:
function myCurriedFn(x) {
  return function(y) {
    return function(z) {
      return function(w) {
        return x * y * z * w
      }
    }
  }
}

myCurriedFn(3)(6)(3)(9)
// Output:
// 486


// Partial application function example:
function myPartApplicationFn(x) {
  return function(y, z) {// Passing two arguments instead of one
    return function(w) {
      return x * y * z * w
    }
  }
}

myPartApplicationFn(3)(6, 3)(9)
// Output:
// 486

Conclusão: Introdução ao currying em JavaScript

O conceito de currying pode ser confuso e difícil de entender. Apenas a palavra em si pode soar estranha. A sintaxe também não é muito útil. Espero que este tutorial tenha sido útil para esclarecer este tópico, ajudando você a entender como e por que currying em JavaScript e como usá-lo.

Postado em Blog
Escreva um comentário