Sé que una forma de implementar esto es recalcular el estado cada vez que llega un cambio, sin embargo, esto parece poco práctico.
Si los cambios aplicados cuando ocurre un evento no son distributivos, de una forma u otra, deberá volver a calcular el estado cada vez que ocurra un evento, ya que el estado final no es más que el estado inicial, más los cambios sucesivos. E incluso si los cambios son distributivos, normalmente desea transformar sucesivamente un estado al siguiente, ya que desea detener su proceso tan rápido como se alcanza un estado determinado, y dado que tiene que calcular el siguiente estado para determinar si uno nuevo es el estado deseado.
En la programación funcional, los cambios de estado generalmente se representan mediante llamadas a funciones y / o parámetros de funciones.
Como no puede predecir cuándo se calculará el estado final, no debe usar la función recursiva sin cola. Un flujo de estados, en el que cada estado se basa en el anterior, podría ser una buena alternativa.
Entonces, en su caso, respondería la pregunta con el siguiente código, en Scala:
import scala.util.Random
val initState = 0.0
def nextState(state: Double, event: Boolean): Double = if(event) state + 0.3 else state - 0.1 // give a new state
def predicate(state: Double) = state >= 1
// random booleans as events
// nb: must be a function in order to force Random.nextBoolean to be called for each element of the stream
def events(): Stream[Boolean] = Random.nextBoolean #:: events()
val states: Stream[Double] = initState #:: states.zip(events).map({ case (s,e) => nextState(s,e)}) // a stream of all the successive states
// stop when the state is >= 1 ;
// display all the states computed before it stopped
states takeWhile(! predicate(_)) foreach println
Lo que puede dar, por ejemplo (simplifiqué el resultado):
0.0
0.3
0.2
0.5
0.8
val states: Stream[Double] = ...
es la línea donde se calculan los sucesivos estados.
El primer elemento de esta secuencia es el estado inicial del sistema. zip
fusiona la secuencia de estados con la secuencia de eventos en una sola secuencia de pares de elementos, cada par es un (estado, evento). map
transforma cada par en un solo valor que es el nuevo estado, calculado en función del estado anterior y el evento asociado. Por lo tanto, un nuevo estado es un estado previamente calculado, más el evento asociado que "modifica" el estado.
Básicamente, usted define un flujo de estados potencialmente infinito, cada nuevo estado es una función del último estado calculado y un nuevo evento. Dado que las secuencias son perezosas en Scala (entre otras), solo se calculan a pedido, por lo que no tiene que calcular estados inútiles y puede calcular tantos estados como desee.
Si solo está interesado en el primer estado que respeta el predicado, reemplace la última línea de código por:
states find predicate get
Que recupera:
res7: Double = 1.1