リモートサーバーにリクエストを送信していますが、ネットワークの信頼性が低いためにリクエストが失敗することがあります。失敗した場合は、リクエストを繰り返したいのですがn
、最大時間です。命令型言語を使用している場合は、リクエスト送信コードをwhileループに配置しますが、関数型の方法で実行したいと思います。
私はこの目的のためにヘルパーを書きました:
/** Repeatedly executes function `f`
* while predicate `p` holds
* but no more than `nTries` times.
*/
def repeatWhile[A](f: => A)(p: A => Boolean)(nTries: Int): Option[A] =
if (nTries == 0) {
None
} else {
f match {
case a if p(a) => repeatWhile(f)(p)(nTries - 1)
case a => Some(a)
}
}
そしてそれをこのように使う:
// Emulating unreliable connection
var n = 0
def receive(): Option[String] =
if (n < 4) {
n += 1
println("No result...")
None
} else {
println("Result!")
Some("Result")
}
// Repeated call
val result = repeatWhile(receive)(!_.isDefined)(10)
ここreceive
で、はテスト目的のばかげた関数です。このコードは、receive
最終的に成功する前に4回の呼び出しを行いSome(Result)
ます。
No result...
No result...
No result...
No result...
Result!
私repeatWhile
はうまく機能しますが、車輪の再発明をしたいと思っています。私は関数型プログラミングを研究していて、私の問題に対する単純な/標準的な解決策があるかどうか知りたいです。
追伸私はさらに多くのヘルパーを定義しました、多分彼らはすでに言語/標準ライブラリにありますか?
/** Repeatedly executes function `f`
* while predicated `p` not holds
* but no more than `nTries` times.
*/
def repeatWhileNot[A](f: => A)(p: A => Boolean)(nTries:Int): Option[A] =
repeatWhile(f)(!p(_))(nTries)
/** Repeatedly executes function `f`
* while it returns None
* but no more than `nTries` times.
*/
def repeatWhileNone[A](f: => Option[A])(nTries:Int): Option[A] =
repeatWhileNot(f)(_.isDefined)(nTries).getOrElse(None)