DEV Community

Guilherme Rodrigues de Melo
Guilherme Rodrigues de Melo

Posted on

Sequências e a importância das funções em Clojure

Olá! Nesse post veremos sobre sequências e a importância das funções para as sequências e para Clojure.

O que são sequências?

Sequências são tipos de dados que abstraem os tipos de dados concretos que armazenam múltiplos valores. Ou seja, listas, mapas, sets e vetores são sequências que podem fazer uso de diversas funções da biblioteca de sequências do Clojure, pois podemos chamar funções iguais para diferentes tipos concretos de sequências. Veremos a seguir exemplos de funções que utilizam desse conceito.

Antes de mostrar os exemplos, devemos entender um outro conceito que já foi implementado no post anterior e que tem o objetivo de deixar o post um pouco mais claro.

Funções de primeira classe e de grandeza superior

Funções são de extrema importância para linguagens que utilizam o paradigma de programação funcional (não me diga, hehe). Mas por que elas são tão importantes? Funções são cidadãs de primeira classe em Clojure, pois são tratadas como valores. Ou seja, podemos passa-las como parâmetro para outras funções, como fazemos com textos e números, por exemplo.

Com a possibilidade de passar funções como parâmetro de outras funções, temos ainda um novo recurso da linguagem que são as funções de grandeza superior. Funções de grandeza superior são funções que recebem outras funções como parâmetro ou que retornam uma função como resultado.

A seguir serão apresentadas funções para manipulação de dados que utilizam os conceitos explicados acima.

Map

A função map nos ajuda a mapear sequências para novos valores. Map recebe como parâmetros uma função e uma sequência. Será aplicada a função para cada item da sequência. Exemplo:

(map inc [1 2 3 4 5])
; (2 3 4 5 6)
Enter fullscreen mode Exit fullscreen mode

No exemplo acima a função inc incrementa um em cada item da sequência (nesse caso send um vetor).

É muito comum precisarmos recuperar apenas um valor de um mapa. No exemplo a seguir utilizamos a keyword :nome como uma função para criar uma nova sequência através do mapa.

; define vetor de mapas de jogadores
(def jogadores 
    [{:nome "Ronaldo"    :idade 43},
     {:nome "Rivaldo"    :idade 47},
     {:nome "Ronaldinho" :idade 40},
     {:nome "Kaká"          :idade 37}])

; Mapeando apenas os nomes dos jogadores 
(map :nome jogadores)  
; ("Ronaldo" "Rivaldo" "Ronaldinho" "Kaká")
Enter fullscreen mode Exit fullscreen mode

Podemos utilizar também a função map para criar novos mapas utilizando mais de uma sequência.

(def jogadores ["Ronaldo" "Rivaldo" "Ronaldinho" "Kaká"])

(def idades [43 47 40 37])

(defn define-jogadores [jogador idade]
    {:nome jogador
     :idade idade})

(map define-jogadores jogadores idades)
; ({:nome "Ronaldo", :idade 43} {:nome "Rivaldo", :idade 47} {:nome "Ronaldinho", :idade 40} {:nome "Kaká", :idade 37})
Enter fullscreen mode Exit fullscreen mode

Reduce

Reduce é uma função que combina todos os itens de uma coleção em um só valor. Reduce, assim como as outras funções, também aplica uma função para cada item da coleção, porém para cada aplicação da função o resultado é acumulado. Exemplo:

(reduce + [1 2 3 4 5])
; 15
Enter fullscreen mode Exit fullscreen mode

No exemplo acima, a cada item que foi somado, o valor somado foi salvo em uma variável interna que é o acumulador. Quando não houver mais itens na coleção o valor acumulado é retornado. É como se estivessemos fazendo assim:

(+ (+ (+ (+ 1 2) 3) 4) 5)
; 15
Enter fullscreen mode Exit fullscreen mode

Reduce aceita também um valor inicial:

(reduce + 10 [1 2 3 4 5])
; 25
Enter fullscreen mode Exit fullscreen mode

Podemos unificar uma sequência de sequências utilizando reduce:

(reduce concat [] [[1 2 3 4 5] [6 7 8 9 10]])
; (1 2 3 4 5 6 7 8 9 10)
Enter fullscreen mode Exit fullscreen mode

Filter

A função filter é utilizada para filtrar valores de uma sequência de acordo com a regra definida pela função passada como parâmetro juntamente com a sequência. Exemplo:

(def pacientes-hospital [{:mes 1 :pacientes-atendidos 150}
    {:mes 2 :pacientes-atendidos 233}
    {:mes 3 :pacientes-atendidos 298}
    {:mes 4 :pacientes-atendidos 144}
    {:mes 5 :pacientes-atendidos 128}])


(filter #(< (:mes %) 3) pacientes-hospital)
; ({:mes 1, :pacientes-atendidos 150} {:mes 2, :pacientes-atendidos 233})
Enter fullscreen mode Exit fullscreen mode

Take-while

A função take-while recebe uma função e uma sequência como parâmetro. A função passada para take-while deve retornar true ou false de acordo com algum critério. Exemplo:

(take-while #(< (:mes %) 3) pacientes-hospital)
;({:mes 1, :pacientes-atendidos 150} {:mes 2, :pacientes-atendidos 233})
Enter fullscreen mode Exit fullscreen mode

No exemplo acima, só serão retornados os registros em que o mês é menor que 3, pois quando a função anônima retorna false, são retornados todos os valores testados até aquele ponto.

A diferença entre o filter e o take-while é que o filter processa toda a sequência enquanto o take-while processa a sequência até uma determinada parte de acordo com regra implementada pela função passada como parâmetro.

Drop-while

A função drop-while segue um raciocínio parecido com a take-while, sendo a única diferença que os registros da sequência serão excluidos até que a função passada como parâmetro retorne false.

(drop-while #(< (:mes %) 3) pacientes-hospital)
; ({:mes 3, :pacientes-atendidos 298} {:mes 4, :pacientes-atendidos 144} {:mes 5, :pacientes-atendidos 128})
Enter fullscreen mode Exit fullscreen mode

Some

A função some também recebe uma função e uma sequência como parâmetro e retorna true quando encontra um elemento que segue a regra da função ou false quando não encontra. Exemplo:

(some #(> (:pacientes-atendidos %) 250) pacientes-hospital)
; true
Enter fullscreen mode Exit fullscreen mode

Sort-By

A função sort-by também recebe uma função e uma sequência como parâmetros. A função sort-by ordena a sequência de acordo com a regra implementada pela função passada como parâmetro. No exemplo abaixo, a sequência é ordenada pelo tamanho do nome:

(sort-by count ["Ronaldo" "Rivaldo" "Ronaldinho" "Kaká"])
; ("Kaká" "Ronaldo" "Rivaldo" "Ronaldinho")
Enter fullscreen mode Exit fullscreen mode

Bem, por enquanto é isso. Espero que tenha aproveitado o conteúdo e nos vemos num post futuro. Até lá! :)

Top comments (0)