Programação funcional do ponto de vista do EcmaScript. Funções puras, lambdas, imunidade

Olá Habr!

Hoje começaremos a falar sobre um tópico muito importante - programação funcional. É difícil superestimar a importância do FP no desenvolvimento moderno da web. A arquitetura de qualquer grande projeto moderno inclui bibliotecas de funções definidas pelo usuário, e haverá perguntas obrigatórias sobre o assunto das entrevistas em qualquer nível.

Introdução à Programação Funcional


A programação funcional (FP) é uma maneira de organizar o código escrevendo um conjunto de funções.

O EcmaScript, sendo uma linguagem de programação multiparadigma, implementa, entre outros, um paradigma funcional. Isso significa que as funções no ES são dados e podem ser passadas para funções, retornadas de funções e podem aceitar as próprias funções. I.e. funções no ES são funções de primeira classe .

As seguintes definições seguem a seguir:

Argumento funcional (funarg) - um argumento cujo valor é uma função.

Uma função de ordem superior (FWP, função de ordem superior, hof) é uma função que aceita funções como argumentos.

Funções com um valor funcional (funções com valor de função) - uma função que retorna uma função.

Todos esses tipos de funções são combinados condicionalmente em funções da primeira classe e, como segue a definição acima, no ES todas as funções são objetos da primeira classe.

Funções puras - o ideal de programação funcional


Funções puras (PF) - sempre retornam um resultado previsto.
Propriedades PF

  • O resultado da execução do PF depende apenas dos argumentos passados ​​e do algoritmo que implementa o PF
  • Não use valores globais
  • Não modifique valores externos ou argumentos passados
  • Não grave dados em arquivos, bancos de dados ou em qualquer outro lugar

Um exemplo de uma função pura:

const add = (x,y) => x+y; 

Um bom exemplo de impureza da função é:

 var first; var second; function testFn() { var a = 10; first = function() { return ++a; } second = function() { return --a; } a = 2; first();//3 } testFn(); first();//4 second();//3 

Imagine como é complicado escrever testes para este exemplo e o quanto isso simplifica para funções puras!

As funções impuras são caracterizadas por um estado externo variável no tempo que complica a manutenção, a compreensão e o teste do código.

Pelo contrário, funções puras são sempre legíveis, testáveis, simplificam a paralelização de cálculos e são fáceis de reutilizar.

Acho que você notou que nos exemplos de funções puras, mudei para a sintaxe ES6. Isso foi feito deliberadamente. Essa sintaxe da função é chamada de "funções da seta", mas na verdade é uma implementação da abstração matemática, inventada há muito tempo. Sobre isso mais.

Lambda - funções


É assim que essa forma de escrita em seta é chamada em matemática e em algumas outras linguagens de programação. A programação funcional está intimamente relacionada ao mat. análise, por isso não se surpreenda.

O termo cálculo Lambda foi introduzido nos anos 30 pela Igreja Alonzo. Em essência, o cálculo lambda nada mais é do que uma forma formal de descrever uma equação matemática. Mais detalhes aqui .

No ES, uma função lambda frequentemente implementa um fechamento:

 const add = x => y => x + y; 

Curto e conciso. A função add é uma lambda que recebe um argumento x, armazena-o em um fechamento e retorna uma função.

Compare com este código:

 funtion add(x) { return function (y) { return x + y; } } 

Obviamente, a primeira opção parece melhor.

Imunidade


Imutável (imutável, imunidade) é um objeto cujo estado não pode ser alterado após a criação. O resultado de qualquer modificação de um objeto desse tipo sempre será um novo objeto, enquanto o objeto antigo não será alterado.

A imutabilidade é o graal de ouro da programação funcional.

Considere um exemplo:

 const impureAddProp = (key, value, object) => { object[key] = value;//   }; const User= { name: 'Alex' }; impureAddProp ('isAdmin', true, User); 

Como você pode ver, neste exemplo, modificamos o objeto User adicionando uma propriedade a ele. Agora, o objeto Usuário é um tipo de "estado compartilhado" para a função impureAddProp e outras funções que o modificarão. Essa abordagem é mais difícil de testar porque Ao alterar qualquer função que interaja com um estado compartilhado, deve-se sempre ter em mente possíveis erros em outras funções.

Do ponto de vista da programação funcional, seria correto:

 const pureAddProp = (key, value, object) => ({ ...object, [key]: value }); const User= { name: 'Alex' }; const Admin= pureAddProp ('isAdmin', true, User); 

Portanto, o objeto Usuário permanecerá inalterado. Estamos modificando uma cópia dos dados, o que é sempre seguro.

Conclusão


Hoje examinamos vários conceitos teóricos importantes. Nós nos familiarizamos com funções puras, a forma lambda de funções de gravação e o conceito de imutabilidade em fp. No entanto, este artigo é um tipo de introdução. As principais idéias, técnicas e "partes difíceis" da programação funcional estarão nos seguintes artigos.

A programação funcional é implementada por muitas bibliotecas. Isso é rambda, e lodash, e muitos outros. Em um projeto real, é claro que você os usará. Sob o capô de qualquer biblioteca, ainda haverá o mesmo javascript nativo; portanto, nos artigos a seguir analisaremos o FP, implementando todos os seus conceitos no JS nativo.

Postscript


Começando a escrever artigos, eu tinha em mente o seguinte plano:

  • escreva traduções de artigos interessantes em inglês
  • destacar várias áreas relevantes em JS (conceitos-chave, OOP em termos de especificações EcmaScript, padrões, programação funcional).

Até o momento, os artigos principais em três áreas já foram escritos:

  1. this e ScopeChain no EcmaScript - aqui descrevi conceitos-chave da especificação como o contexto de execução, a palavra-chave this e a propriedade de contexto ScopeChain (cadeia de escopo). No contexto dessa direção, meu artigo sobre o ambiente e fechamento Lexical foi publicado literalmente hoje.
  2. Uma análise do EcmaScript sobre a teoria geral da OOP - aqui foi descrita a diferença entre tipagem de classe estática e organização dinâmica de protótipos, o modelo de delegação e a tipagem de pato foram desmontados
  3. Padrões elegantes no JavaScript moderno (série de compilação Bill Sourour no ciclo) - aqui estão dois padrões que podem ser úteis em algumas situações. Minha abordagem em termos de padrões é bastante simples: é melhor conhecer o maior número possível de padrões, porque mais cedo ou mais tarde, será útil

E agora é a vez da programação funcional. No futuro, escreverei artigos na continuação de cada uma dessas áreas. Por exemplo, o artigo a seguir será sobre os principais conceitos de OOP: encapsulamento, abstração, impurezas (e traços), interfaces, etc. ... também planejo falar sobre como o OOP no ES é implementado sob o capô, ou seja, sobre as propriedades de [[Prototype]], [[Class]] e muito mais. Fale sobre como a v8 cria entidades e instâncias de classes, funções.

Muitas perguntas surgem nos comentários, então eu gostaria de explicar as metas que estabeleci para meus artigos. Não escrevo tutoriais nem revisto a documentação. Na minha opinião, isso não faz sentido. Eu não aconselho você com certos instrumentos ou padrões, a escolha deles é inteiramente sua.

Nos artigos, reviso os conceitos, digo como eles estão organizados sob o capô (na minha opinião, isso melhora a compreensão do que escrevemos e por que escrevemos dessa maneira), ou falo sobre algumas coisas que ampliam meus horizontes. Na minha opinião, isso é muito importante. Dê uma olhada em empresas como Yandex ou Edadil, elas constantemente falam sobre algum tipo de idéias originais. Esses são bitmaps na reação, então o aplicativo vue está quase completamente nas classes es6. A maioria dos desenvolvedores da web nunca teria pensado nisso. Isso requer uma visão ampla.

Eu mesmo estudei e estudei a Web dessa maneira, ou seja, Depois de ler um tutorial ou uma doca, tento entender como a ferramenta descrita funciona sob o capô, para entender sua mecânica interna.

Até artigos futuros, amigos!

Source: https://habr.com/ru/post/pt474702/


All Articles