estoy pasando por la programación en Scala 2ª edición por Odersky, cuchara, y Venners, y este ejemplo me tiró para un bucle ya que parecía ir en contra de lo que pensaba era cierto acerca de la programación funcional y inmutabilidad. En el ejemplo (y anteriormente en el libro en el cap. 18), los autores afirman que las operaciones sobre un objeto todavía puede ser "puramente funcional" incluso cuando esas operaciones podrían mutar el estado interno del objeto. El ejemplo, que está en la p.442, Cap. 19, es la siguiente:cola Funcional De Programación En Scala
class Queue[+T] private (
private[this] var leading: List[T],
private[this] var trailing: List[T]
) {
private def mirror() =
if (leading.isEmpty) {
while (!trailing.isEmpty) {
leading = trailing.head :: leading
trailing = trailing.tail
}
}
def head: T = {
mirror()
leading.head
}
def tail: Queue[T] = {
mirror()
new Queue(leading.tail, trailing)
}
def enqueue[U >: T](x: U) =
new Queue[U](leading, x :: trailing)
}
La justificación es que, con tal de que los efectos secundarios no son visibles para los clientes, algo como esto puede ser considerado funcional. Creo que puedo ir detrás de eso ... Es decir, estrictamente hablando, eso es lo que define una función. Pero es cierto (y no estoy realmente muy inteligente acerca de lo que las garantías de JVM modelo de memoria), pero no están ahí los problemas potenciales con que en este código?
Por ejemplo, si dos hilos se ejecutan las operaciones en esta cola, que se parece a esto para empezar:
Leading: Nil
Trailing: List(1,2,3,4)
¿No es posible que un hilo podría llamar a la cabeza() para llegar a este punto en el espejo() antes de ser descheduled:
private def mirror() =
if (leading.isEmpty) {
while (!trailing.isEmpty) {
leading = trailing.head :: leading
> trailing = trailing.tail
}
}
momento en el que la cola se parece a esto:
Leading: List(1)
Trailing: List(1,2,3,4)
Y cuando un segundo subproceso llama a la cola(), mientras que el primero no se encuentra activo, esto sería devuelto:
Leading: Nil
Trailing: List(1,2,3,4)
Mientras que si la cabeza de la primera rosca() llamada fuera para terminar, este sería devuelto después de una cola posterior() llamar en esa lista:
Leading: List(2,3,4)
Trailing: Nil
que es cierto que no soy muy bueno para este tipo de cosas y programación concurrente que realmente está mindbending para mí, como estoy seguro de que es para mucha gente, estoy solo curiosidad por lo que me estoy perdiendo aquí.
creo que estás en lo correcto. Supongo que se podría decir que la "sensación funcional" se rompe si la usa más de un hilo. ¿Se supone que los programas funcionales son simultáneos? No lo sé. – Owen