Estilo Ramda: Imutabilidade e Arrays

1. Primeiros passos
2. Combine as funções
3. Uso parcial (currying)
4. Programação declarativa
5. Notação quintessencial
6. Imutabilidade e objetos
7. Imutabilidade e matrizes
8. Lentes
9. Conclusão


Este post é a sétima parte de uma série de artigos de programação funcional denominados Ramda Style Thinking.


Na sexta parte, falamos sobre como trabalhar com objetos JavaScript em um estilo funcional e imutável.


Neste post, falaremos sobre trabalhos semelhantes com matrizes.


Lendo elementos da matriz


Na sexta parte, aprendemos sobre as várias funções do Ramda para ler propriedades de objetos, como prop , pick e has . O Ramda possui ainda mais métodos para ler elementos de array.


O equivalente de prop para uma matriz é enésimo ; o equivalente para pick é fatia e o equivalente para has é contém . Vamos dar uma olhada neles.


 const numbers = [10, 20, 30, 40, 50, 60] nth(3, numbers) // => 40 (  ) nth(-2, numbers) // => 50 (     ) slice(2, 5, numbers) // => [30, 40, 50] (. ) contains(20, numbers) // => true 

A fatia pega dois índices e retorna uma sub-matriz que começa no primeiro índice (começando do zero) e inclui todos os elementos até o segundo índice, mas não incluindo o elemento desse índice.


Obter acesso ao primeiro e ao último elementos de uma matriz é bastante comum, portanto, o Ramda fornece funções curtas para esses casos, head e last . Ele também fornece funções para obter todos os elementos, exceto o primeiro ( cauda ), todos, exceto o último ( init ), os primeiros N elementos ( take (N) ) e os últimos N elementos ( takeLast (N) ). Vamos dar uma olhada neles em ação.


 const numbers = [10, 20, 30, 40, 50, 60] head(numbers) // => 10 tail(numbers) // => [20, 30, 40, 50, 60] last(numbers) // => 60 init(numbers) // => [10, 20, 30, 40, 50] take(3, numbers) // => [10, 20, 30] takeLast(3, numbers) // => [40, 50, 60] 

Adicionar, atualizar e excluir elementos da matriz


Estudando como trabalhar com objetos, aprendemos sobre as funções assoc , dissoc e omit para adicionar, atualizar e excluir propriedades.


Como matrizes têm uma estrutura de dados ordenada, temos vários métodos que fazem o mesmo trabalho que assoc para objetos. Os mais comuns são inserção e atualização , mas o Ramda também fornece métodos de acréscimo e pré- acréscimo para casos típicos de inclusão de elementos no início e no final de uma matriz. insert , append e acrescentar novos elementos à matriz; update "substitui" um elemento específico na matriz por um novo valor.


Como você pode esperar de uma biblioteca funcional, todas essas funções retornam uma nova matriz com as alterações esperadas; a matriz original nunca muda.


 const numbers = [10, 20, 30, 40, 50, 60] insert(3, 35, numbers) // => [10, 20, 30, 35, 40, 50, 60] append(70, numbers) // => [10, 20, 30, 40, 50, 60, 70] prepend(0, numbers) // => [0, 10, 20, 30, 40, 50, 60] update(1, 15, numbers) // => [10, 15, 30, 40, 50, 60] 

Para combinar dois objetos em um, aprendemos anteriormente sobre o método de merge . O Ramda também fornece um método concat para executar a mesma operação com matrizes.


 const numbers = [10, 20, 30, 40, 50, 60] concat(numbers, [70, 80, 90]) // => [10, 20, 30, 40, 50, 60, 70, 80, 90] 

Observe que a segunda matriz se juntou à primeira. Isso parece lógico ao usar esse método separadamente de outro código, mas, como na merge , essa lógica pode não levar exatamente ao que seria de esperar se usássemos esse método em nosso pipeline. Achei útil escrever uma função auxiliar, concatAfter : const concatAfter = flip(concat) , para usá-la em meus pipelines.


O Ramda também oferece várias opções para excluir itens. remove remove itens por seu índice, enquanto sem remove por seu valor. Também existem métodos como drop e dropLast para casos típicos quando removemos elementos do início ou do fim de uma matriz.


 const numbers = [10, 20, 30, 40, 50, 60] remove(2, 3, numbers) // => [10, 20, 60] without([30, 40, 50], numbers) // => [10, 20, 60] drop(3, numbers) // => [40, 50, 60] dropLast(3, numbers) // => [10, 20, 30] 

Observe que remove aceita um índice e uma quantia, enquanto a slice aceita dois índices. Essa inconsistência pode ser confusa se você não souber.


Conversão de elemento


Como nos objetos, podemos desejar atualizar o elemento da matriz aplicando a função ao valor original.


 const numbers = [10, 20, 30, 40, 50, 60] //      10 update(2, multiply(10, nth(2, numbers)), numbers) // => [10, 20, 300, 40, 50, 60] 

Para simplificar esse caso típico, o Ramda fornece um método de ajuste que funciona como evolve para objetos. Mas, ao contrário do evolve , o adjust funciona com apenas um elemento da matriz.


 const numbers = [10, 20, 30, 40, 50, 60] //      10 adjust(multiply(10), 2, numbers) 

Observe que os dois primeiros argumentos a serem adjust são inversos ao compará-los com a update . Isso pode ser uma fonte de erros, mas faz sentido quando você considera um aplicativo parcial. Você pode fazer o adjust(multiply(10)) por si mesmo e, posteriormente, decidir qual índice da matriz alterar usando-a.


Conclusão


Agora, temos ferramentas para trabalhar com matrizes e objetos em um estilo declarativo e imutável. Isso nos permite criar programas que consistem em pequenos blocos de construção funcionais, combinando funções que farão o que precisamos e tudo isso sem alterar todas as nossas estruturas de dados.


Seguinte


Aprendemos como ler, atualizar e transformar propriedades de objetos e elementos de matrizes. Ramda fornece outras ferramentas básicas para realizar essas operações, lentes. O próximo artigo sobre lentes nos mostrará como eles funcionam.

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


All Articles