Até agora lidamos com pedaços discretos de dados: um número, uma string, um valor. Em programação, no entanto, é mais comum o caso em que temos que lidar com grupos de dados.
Clojure tem ótimas facilidades para trabalhar com esses grupos, ou coleções de dados. Não só nos dá quatro tipos diferentes de coleções mas também nos permite acessar de uma maneira uniforme todos esses tipos de coleções junto.
Um vetor é uma coleção sequencial de valores. Um vetor pode estar vazio. Um vetor pode ter valores de diferentes tipos. Cada valor em um vetor é numerado começando em 0, e esse número é chamado de índice. O índice é usado para consultar cada valor de dentro do vetor quando estivermos procurando algo.
Para imaginar um vetor, pense em uma caixa separada em uma quantidade de divisórias de mesmo tamanho. Cada uma dessas divisórias tem um número. Você pode colocar algum dado dentro de cada divisória e sempre saber onde procurar esse dado no número da divisória.
Note que os números começam em zero. Isso pode parecer estranho, mas no geral em programação começamos a contar do zero.

Vetores são geralmente escritos entre colchetes
[]com qualquer quantidade de valores separados por espaços. Estes são alguns exemplos de vetores:
[1 2 3 4 5]
[56.9 60.2 61.8 63.1 54.3 66.4 66.5 68.1 70.2 69.2 63.1 57.1]
[]
As duas próximas funções são usadas pra criar novos vetores. A função
vectorrecebe um número qualquer de itens e os coloca em um vetor novo.conjé uma função interessante que você verá sendo usada com todas as estruturas de dados. Com vetores, ela recebe um vetor e um item e devolve um novo vetor que tem esse item adicionado ao final dos itens do vetor recebido. Por que o nomeconj?conjé abreviação de conjoin, que significa juntar ou combinar. E é isso que estamos fazendo: Estamos juntando o novo item ao vetor.
(vector 5 10 15)
;=> [5 10 15]
(conj [5 10] 15)
;=> [5 10 15]
Agora veja estas quatro funções.
countnos dá a quantidade de itens que o vetor tem.nthnos dá o enézimo item do vetor. Note que começamos a contar do 0, então no exemplo chamarnthcom o número 1 nos dá o que chamaríamos de segundo elemento se não estivéssemos programando.firstdevolve o primeiro item da coleção.restretorna todos os itens exceto o primeiro. Tente não pensar sobre isso enthao mesmo tempo, pois pode ser confuso.
(count [5 10 15])
;=> 3
(nth [5 10 15] 1)
;=> 10
(first [5 10 15])
;=> 5
(rest [5 10 15])
;=> (10 15)
Mapas são conjuntos de chave e valores associados a elas. Você pode pensar nelas como se fossem um dicionário: você procura por coisas usando uma palavra (uma palavra-chave/keyword) e consegue ver a sua definição (seu valor). Se você já programou em outra linguagem, você pode já ter visto algo parecido com mapas – talvez chamados de dicionários, hashes ou arrays associativos.

Para escrever mapas alternamos chaves e valores, colocando chaves
{}em volta de todas elas.
Mapas são útes pois conseguem guardar dados da maneira que normalmente já pensamos sobre eles. Pense no nosso exemplo hipotético, Sally Brown. Um mapa pode guardar o seu nome e sobrenome, seu endereço, sua comida favorita ou qualquer outra coisa. É uma forma simples de coletar estes dados e ser fácil de procurar depois. O último exemplo é um mapa vazio. É um mapa que está pronto pra guardar alguma coisa, mas ainda não tem nada.
{:first "Sally" :last "Brown"}
{:a 1 :b "two"}
{}
assocedissocsão funções complementares: elas associam e desassociam itens em um mapa. Veja como colocamos o sobrenome “Brown” no mapa comassoc, e depois o removemos comdissoc.mergemistura dois mapas para formar um novo mapa com todos os seus elementos juntos.
(assoc {:first "Sally"} :last "Brown")
;=> {:first "Sally", :last "Brown"}
(dissoc {:first "Sally" :last "Brown"} :last)
;=> {:first "Sally"}
(merge {:first "Sally"} {:last "Brown"})
;=> {:first "Sally", :last "Brown"}
count, toda coleção tem essa função. Por que você acha que a resposta é dois?countnos devolve o número de associações.
Como mapas são pares de chave-valor, a chave é usada para pegar o valor de um mapa. Um dos jeitos mais usados em Clojure são os exemplos abaixo. Podemos usar uma keyword como se fosse uma função para buscar os valores dentro do mapa. No último exemplo, passamos a chave
:INEXISTENTEcomo último argumento. Isso funciona para quando a chave que procuramos não existe no mapa.
(count {:first "Sally" :last "Brown"})
;=> 2
(get {:first "Sally" :last "Brown"} :first)
;=> "Sally"
(get {:first "Sally"} :last)
;=> nil
(get {:first "Sally"} :last :INEXISTENTE)
;=> :INEXISTENTE
Também temos
keysevals, que são bem simples: retornam as chaves e os valores do mapa. A ordem não é garantida, então poderiamos ter como resultado(:first :last)ou(:last :first)
(keys {:first "Sally" :last "Brown"})
;=> (:first :last)
(vals {:first "Sally" :last "Brown"})
;=> ("Sally" "Brown")
Após a criação, queremos salvar um novo valor associado à chave. A função
assocpode ser usada para associar um novo valor a uma chave já existente. Também existe uma função útil chamadaupdate. Esta função recebe o mapa e a chave com uma função. O valor da chave especificada vai ser o primeiro argumento da função passada. A funçãoupdate-infunciona como aupdate, mas recebe um vetor de chaves para atualizar um caminho dentro de um mapa aninhado.
(def hello {:count 1 :words "hello"})
(update hello :count inc)
;=> {:count 2, :words "hello"}
(update hello :words str ", world")
;=> {:count 1, :words "hello, world"}
(def mine {:pet {:age 5 :name "able"}})
(update-in mine [:pet :age] - 3)
;=> {:pet {:age 2, :name "able"}}
Voltar ao primeiro slide, ou ir para o índice do currículo.