Deixe-me primeiro dizer que tenho bastante experiência em Java, mas apenas recentemente me interessei por linguagens funcionais. Recentemente comecei a estudar Scala, que parece ser uma linguagem muito legal.
No entanto, tenho lido sobre a estrutura de Ator do Scala em Programação em Scala e há uma coisa que não entendo. No capítulo 30.4 ele diz que usar em reactvez de receivetorna possível reutilizar threads, o que é bom para o desempenho, uma vez que threads são caros na JVM.
Isso significa que, desde que me lembre de ligar em reactvez de receive, posso iniciar quantos atores eu quiser? Antes de descobrir Scala, estive brincando com Erlang, e o autor de Programming Erlang se orgulha de gerar mais de 200.000 processos sem suar a camisa. Eu odiaria fazer isso com threads Java. Que tipo de limites estou considerando no Scala em comparação com Erlang (e Java)?
Além disso, como essa reutilização de thread funciona no Scala? Vamos supor, para simplificar, que tenho apenas um segmento. Todos os atores que eu iniciar serão executados sequencialmente neste tópico ou ocorrerá algum tipo de troca de tarefas? Por exemplo, se eu iniciar dois atores que trocam mensagens de pingue-pongue, correrei o risco de um deadlock se eles forem iniciados no mesmo thread?
De acordo com a Programação em Scala , escrever atores para usar reacté mais difícil do que com receive. Isso parece plausível, já reactque não retorna. No entanto, o livro continua mostrando como você pode colocar reactum loop dentro de um usando Actor.loop. Como resultado, você obtém
loop {
react {
...
}
}
que, para mim, parece muito semelhante a
while (true) {
receive {
...
}
}
que é usado anteriormente no livro. Ainda assim, o livro diz que “na prática, os programas precisarão de pelo menos alguns receive”. Então, o que estou perdendo aqui? O que pode receivefazer isso reactnão pode, além de retornar? E por que eu me importo?
Finalmente, voltando ao cerne do que eu não entendo: o livro continua mencionando como o uso reacttorna possível descartar a pilha de chamadas para reutilizar o thread. Como isso funciona? Por que é necessário descartar a pilha de chamadas? E por que a pilha de chamadas pode ser descartada quando uma função termina lançando uma exceção ( react), mas não quando termina retornando ( receive)?
Tenho a impressão de que Programação em Scala tem passado por cima de algumas das questões-chave aqui, o que é uma pena, porque de outra forma é um livro realmente excelente.