これを実装する1つの方法は、変更が到着するたびに状態を再計算することですが、これは実際的ではないようです。
イベントの発生時に適用された変更が分散的でない場合、何らかの形で、最終状態は初期状態とそれに続く変化に過ぎないため、イベントが発生するたびに状態を再計算する必要があります。また、変更が分散的である場合でも、通常、状態を次の状態に連続的に変換する必要があります。これは、特定の状態に達したらすぐにプロセスを停止し、次の状態を計算して次の状態を判断する必要があるためです。新しいのは指名手配状態です。
関数型プログラミングでは、状態の変化は通常、関数呼び出しや関数パラメーターによって表されます。
最終状態がいつ計算されるか予測できないため、非末尾再帰関数を使用しないでください。各状態が前の状態に基づいている状態のストリームは、良い代替案になる可能性があります。
だからあなたの場合、私は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
たとえば、次のようになります(出力を簡略化しました)。
0.0
0.3
0.2
0.5
0.8
val states: Stream[Double] = ...
連続する状態が計算される行です。
このストリームの最初の要素は、システムの初期状態です。zip
状態のストリームをイベントのストリームとマージして、各ペアが(状態、イベント)である要素のペアの単一のストリームにマージします。map
各ペアを、古い状態と関連するイベントの関数として計算された新しい状態である単一の値に変換します。したがって、新しい状態は、以前に計算された状態と、その状態を「変更」する関連イベントです。
したがって、基本的に、潜在的に無限の状態のストリームを定義します。新しい状態はそれぞれ、最後に計算された状態の関数であり、新しいイベントです。Scalaではストリームが(特に)遅延しているため、オンデマンドでしか計算されないため、無駄な状態を計算する必要がなく、必要なだけ状態を計算できます。
述語を尊重する最初の状態のみに関心がある場合は、コードの最後の行を次のように置き換えます。
states find predicate get
取得するもの:
res7: Double = 1.1