Conta a frequência das letras em textos recorrendo a computação paralela.
O paralelismo consiste em fazer em paralelo coisas que também podem ser feitas sequencialmente. Um exemplo comum é contar a frequência de letras. Usa o paralelismo para calcular a frequência total de cada letra numa lista de textos.
As tarefas são a principal abstração para escrever código assíncrono em Lean. São leves e podem ser executadas em paralelo noutra thread, ou em simultâneo na mesma thread.
As tarefas podem ser puras ou impuras.
As tarefas puras criam-se com Task.spawn, que aceita um cálculo puro.
As tarefas impuras criam-se a partir de cálculos IO usando, por exemplo, IO.asTask, que eleva um IO α a um Task α dentro da mónade IO.
Neste exercício, a função calculateFrequencies é monádica e devolve um IO (Std.TreeMap Char Nat).
Isto permite usar tarefas impuras através de IO.asTask e também torna possível criar tarefas puras para cálculos intermédios antes de devolver o valor final.
Enquanto linguagem funcional, a maioria dos valores em Lean é persistente, ou seja, imutável. As operações que parecem modificar um valor produzem, na verdade, um novo valor com as alterações pedidas. Isto significa que a memória pode muitas vezes ser partilhada em segurança entre tarefas sem introduzir corridas de dados.
Repara, no entanto, que nem todas as estruturas de dados são igualmente adequadas a uma utilização persistente.
Por exemplo, atualizar um único elemento de um Array exige normalmente copiar o array inteiro.
O mesmo acontece com Std.HashSet e Std.HashMap.
Para tornar eficientes estas estruturas de dados, o Lean recorre à contagem de referências. Enquanto um valor tiver uma referência única, as atualizações podem ser feitas de forma destrutiva, evitando cópias desnecessárias.
Outras estruturas de dados, como List, Std.TreeSet e Std.TreeMap, foram concebidas para partilhar estrutura internamente.
Reutilizam os nós inalterados quando se fazem atualizações, para que vários valores possam partilhar referências a esses nós.
Por isso, modificar uma parte da estrutura não exige normalmente copiar o valor inteiro.
Isto torna-as especialmente adequadas para serem partilhadas entre tarefas.
O tempo de execução de cada teste é medido em nanossegundos com IO.monoNanosNow e mostrado juntamente com os resultados.
Podes experimentar abordagens diferentes e verificar o impacto que têm no desempenho em tempo de execução.
Inscreve-te no Exercism para aprenderes e dominares Lean com 100 exercícios, e mentoria humana real, tudo grátis.
Exploramos as diferenças entre concorrência e paralelismo, analisando as diferentes abordagens adotadas por linguagens como JavaScript, Go, Elixir e Rust.