Prima di tutto vorrei dire che ho molta esperienza con Java, ma solo di recente mi sono interessato ai linguaggi funzionali. Recentemente ho iniziato a guardare Scala, che sembra un linguaggio molto carino.
Tuttavia, ho letto del framework degli attori di Scala in Programming in Scala , e c'è una cosa che non capisco. Nel capitolo 30.4 si dice che usare react
invece di receive
rende possibile riutilizzare i thread, il che è positivo per le prestazioni, poiché i thread sono costosi nella JVM.
Questo significa che, purché mi ricordi di chiamare react
invece di receive
, posso avviare quanti attori voglio? Prima di scoprire Scala, ho suonato con Erlang, e l'autore di Programming Erlang si vanta di aver generato oltre 200.000 processi senza sudare. Non vorrei farlo con i thread Java. Che tipo di limiti sto osservando in Scala rispetto a Erlang (e Java)?
Inoltre, come funziona il riutilizzo di questo thread in Scala? Supponiamo, per semplicità, che io abbia un solo thread. Tutti gli attori che inizio correranno in sequenza in questo thread o si verificherà una sorta di cambio di attività? Ad esempio, se avvio due attori che si scambiano messaggi ping-pong, rischierò un deadlock se vengono avviati nello stesso thread?
Secondo Programming in Scala , scrivere attori da usare react
è più difficile che con receive
. Questo sembra plausibile, poiché react
non ritorna. Tuttavia, il libro continua a mostrare come si può inserire react
un loop usando Actor.loop
. Di conseguenza, ottieni
loop {
react {
...
}
}
che, a me, sembra abbastanza simile a
while (true) {
receive {
...
}
}
che viene utilizzato in precedenza nel libro. Tuttavia, il libro dice che "in pratica, i programmi avranno bisogno di almeno alcuni programmi receive
". Allora cosa mi manca qui? Cosa può receive
fare che react
non può, oltre a tornare? E perché mi interessa?
Infine, arrivando al nocciolo di ciò che non capisco: il libro continua a menzionare come using react
renda possibile scartare lo stack di chiamate per riutilizzare il thread. Come funziona? Perché è necessario eliminare lo stack di chiamate? E perché lo stack di chiamate può essere scartato quando una funzione termina lanciando un'eccezione ( react
), ma non quando termina restituendo ( receive
)?
Ho l'impressione che Programming in Scala abbia sorvolato su alcune delle questioni chiave qui, il che è un peccato, perché altrimenti è un libro davvero eccellente.