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 react
vez de receive
torna 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 react
vez 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á react
que não retorna. No entanto, o livro continua mostrando como você pode colocar react
um 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 receive
fazer isso react
nã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 react
torna 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.