Aguarde...

22 de novembro de 2021

Uma breve introdução ao operador de pipeline e tubulação em JavaScript

Uma breve introdução ao operador de pipeline e tubulação em JavaScript

A programação funcional fornece muitos conceitos úteis. Um desses conceitos é operador de duto e tubulação. Este tutorial ajudará você a entender o que é o operador de pipeline e a tubulação, como funcionam e como usá-los. Você também aprenderá a criar sua própria função de pipe em JavaScript.

Uma breve introdução

O operador de pipeline é um dos recursos discutidos há muito tempo, mas nunca se tornou um recurso da linguagem JavaScript. Isso mudou e o operador do duto entrou como rascunho no estágio 1 do processo TC39 . Em 2021 , passou do estágio 1 para o estágio 2.

Isso significa que o operador de pipeline ainda não é um recurso estável da linguagem JavaScript e sua especificação pode mudar. No entanto, já existe um plugin do Babel que nos permite trabalhar com este recurso. Dito isso, nem mesmo precisamos do plug-in ou do recurso para emular o que o operador de pipeline faz.

Podemos pegar a sintaxe JavaScript existente e criar nossa própria função que levará a resultados semelhantes aos do operador de pipeline. Mas antes de fazermos isso, vamos dar uma olhada no operador de pipeline e na tubulação.

Tubulação simplificada

A ideia das funções de tubulação pode parecer difícil de entender, mas não é. Simplificando, canalizando sobre pegar alguma entrada e passá-la para uma função e, em seguida, enviá-la para outra função. Dessa forma, você pode pegar algum valor como entrada e enviá-lo por meio de uma sequência de funções para obter um valor como saída.

Uma maneira de fazer isso é usando o encadeamento de métodos . Com essa abordagem, você pega um valor e chama algum método nele. Então, em vez de chamar outro método no resultado da chamada anterior separadamente, você “encadeia” o próximo método primeiro.

// Chaining example with string:
const sentence = '  There - is some -  mess around.  '
// Modifying the string with method chaining:
const cleanedSentence = sentence
  .replace(/-/g, ' ')
  .replace(/\s+/g, ' ')
  .trim()

console.log(cleanedSentence)
// Output:
// 'There is some mess around.'

Outra opção é usar tubulação, mas sem o operador de tubulação. Esta solução funciona bem com funções personalizadas. Em vez de encadear funções, você passa uma chamada de função como argumento para outra chamada de função. Dessa forma, você pode passar um valor retornado por uma função para outra para obter o resultado que você precisa.

// Piping example:
// Define some functions:
const add = (num) => num1 + 10
const subtract = (num) => num1 - 5
const multiply = (num) => num1 * 9

// Use piping to pass value through cascade of functions:
const num = multiply(add(subtract(15)))
console.log(num)
// Output:
// 180

Existe um problema com isso. Seu código pode rapidamente se tornar uma pilha de confusão ilegível conforme você adiciona mais e mais chamadas de função. Agora, vamos dar uma olhada em como podemos lidar com isso com a ajuda do operador de pipeline.

O operador do pipeline

Em JavaScript, o operador de pipeline usa uma sintaxe muito específica. Ele usa este |>símbolo de “tubo” . Quando você quiser usar este operador, você tem que colocá-lo em um local específico. Este lugar é entre o valor que você deseja passar para uma chamada de função e a função que você deseja chamar.

Se você quiser canalizar várias funções, coloque o |>símbolo entre cada uma delas. Lembre-se de que você não coloca o |>símbolo após a última função. A última função é a última coisa na cadeia. Vamos demonstrar o operador de pipeline reescrevendo o exemplo com piping para essa nova sintaxe.

// Without pipeline operator:
const add = (num1, num2) => num1 + 10
const subtract = (num1, num2) => num1 - 5
const multiply = (num1, num2) => num1 * 9

const num = multiply(add(subtract(15)))

// Log the value of "num":
console.log(num)
// Output:
// 180


// With pipeline operator:
const numPiped = 15 |> add |> subtract |> multiply

// Log the value of "num":
console.log(numPiped)
// Output:
// 180

// Notes:
// 1. Value 15 gets passed to add() fn
// 2. The value returned by add() fn is passed to subtract()
// 3. The value returned by subtract() fn is passed to multiply()
// 4. The value returned by multiply() fn is assigned to numPiped variable

Como você pode ver, nosso código é muito mais legível quando usamos o operador de pipeline. Pode demorar um pouco para se acostumar com a nova sintaxe e algumas diferenças, como parênteses ausentes nas chamadas de função.

Função de tubulação personalizada

O operador de pipeline parece útil. O problema que pode nos impedir de começar a usá-lo é que ele está apenas no estágio 2. Isso significa que não há garantia de que ele chegará à especificação JavaScript. Mesmo que acabe dando certo, não sabemos quando. Já demorou muito para a operadora chegar ao estágio 2.

Felizmente, existem duas opções. O primeiro é o plugin do Babel . Este plugin permitirá o uso do operador de pipeline agora, antes de atingir o estágio 3 ou 4. Outra opção é criar nossa própria função de pipeline personalizada usando o JavaScript atual. Vamos nos concentrar na segunda opção e criar a função personalizada.

Esta função de tubulação será simples. O que precisamos é de uma função que aceite um número desconhecido de argumentos. Esta função irá iterar todos os argumentos, que serão funções, e chamar cada um. Cada chamada de função retornará um valor. Nossa função de tubulação pegará cada valor e o adicionará ao anterior.

Para cada chamada, nossa função de tubulação usará o valor retornado anteriormente como um argumento para a chamada atual. Depois que a última função for chamada, nossa função de tubulação adicionará o último valor ao acumulador de valores anteriores e retornará o valor final. Isso pode parecer complicado, mas podemos fazer isso facilmente com o método reduce () .

// Functions to pipe:
const add = (num1, num2) => num1 + 10
const subtract = (num1, num2) => num1 - 5
const multiply = (num1, num2) => num1 * 9

// Custom piping function
/**
 * Pipes functions and returns a single value
 * @param {Array} args - array composed of initial value and functions
 * @return {any}
 */
const pipeFn = (...args) => args.reduce((acc, fn) => fn(acc));

// Testing custom piping function:
const numPiped = pipeFn(15, add, subtract, multiply)

console.log(numPiped)
// Output:
// 180

Como você pode ver, a função de tubulação personalizada é muito simples. É composto de duas coisas, array de argumentos e um método de redução. Uma coisa que alguns desenvolvedores podem não gostar é o valor inicial passado como o primeiro argumento. Uma maneira de corrigir isso é usando currying .

Podemos remover o valor inicial da matriz de argumentos com funções na primeira chamada e movê-lo para uma chamada de função separada.

// Functions for piping:
const add = (num1, num2) => num1 + 10
const subtract = (num1, num2) => num1 - 5
const multiply = (num1, num2) => num1 * 9

// Updated piping function:
const pipeFn = (...args) => val => args.reduce((acc, fn) => fn(acc), val);

// Test:
const numPiped = pipeFn(add, subtract, multiply)(15)
console.log(numPiped)
// Output:
// 180

Nota final

Vale a pena repetir que, no momento em que escrevo este artigo, o operador de pipeline está no estágio 2. Embora haja um plug-in Babel que pode transpilar a sintaxe do operador de pipeline em JavaScript, os navegadores modernos podem entender que eu usaria esse recurso no código de produção. Muita coisa pode mudar e muita coisa pode quebrar.

Para quem deseja usar esse recurso, eu sugeriria o uso de alguma implementação customizada, uma que usamos ou alguma alternativa. Isso garantirá que seu código funcione independentemente das alterações na proposta da operadora. E quando o operador está ausente, você pode facilmente migrar sua implementação personalizada, se desejar.

Conclusão: uma breve introdução ao operador de pipeline, e piping, em JavaScript

O operador de pipeline facilita o uso do conceito de funções de piping, enquanto mantém seu código legível e curto. Este operador ainda não é uma parte oficial do JavaScript. No entanto, isso não significa que podemos usá-lo hoje, seja diretamente com a ajuda do Babel ou indiretamente por meio de implementação customizada.

Postado em Blog
Escreva um comentário