3

ネットワーク サービスに特定のトークンを照会し、そのトークンを予想されるトークンと比較する Scala コードがいくつかあります。予想されるトークンが見つかるまで、または N 回試行に失敗するまで、予想されるトークンを照会し続けたいと考えています。

Java-tacular の方法でそれを行う方法は次のとおりです。

def keepLooking(expectedToken: String, maxTries: Int) {
  var tries = 0
  var token = ""
  do {
    Thread.sleep(tries * 1000) // don't overwhelm the service by calling it too fast!

    token = makeSomeNetworkCall()
    tries += 1
  } while (tries <= maxTries && token != expectedToken)
}

もっと機能的にしてほしい。私には1つの考えがあります:

1.to(maxTries) map { tryNum =>
  Thread.sleep(tryNum - 1 * 1000) // don't overwhelm the service by calling it too fast!
  makeSomeNetworkCall()
} exists (_ == expectedToken)

しかし、これには 2 つの疑問が生じます。

  1. mapは怠惰なので、exists短絡する必要がありますよね?2 回目の呼び出しでトークンが見つかった場合、10 回のネットワーク呼び出しを行いたくありません。
  2. 私が望むものを達成するためのより慣用的な方法はありますか?
4

4 に答える 4

4

1.への回答:

mapRangeを aに変換する場合にのみ遅延しStreamます。

(1 to 10).toStream map (i => { println(i); i }) exists (_ == 2)
// will print
// 1
// 2
于 2013-11-07T21:57:53.370 に答える
3

怠惰かどうかmapは、一般に、コレクションの種類によって異なります。.toStream確実に遅延させるには、 orを使用できます.view(後者は結果をキャッシュしないため、通常はそれを選択します)。

それ以外は問題ないように思えますが、応答から実際にデータを取得する必要がある場合には機能しません (この質問で必要なものではないことはわかっていますが、しようとしています)。ここではより一般的に考えてください)。

于 2013-11-07T21:57:36.457 に答える
1

質問 2 については、独自の を作成できますStream

scala>  val keepLooking: Stream[Tuple2[Int, String]] = (0, "a") #:: (1, "aa") #:: keepLooking.tail.map { n => (n._1 + 1, n._2 + "a")}
keepLooking: Stream[(Int, String)] = Stream((0,a), ?)

scala> keepLooking.take(20).find(_._2 == "aaa")
res0: Option[(Int, String)] = Some((2,aaa))

scala> keepLooking.take(20).find(_._2 == "xxx")
res1: Option[(Int, String)] = None

これは簡単な例です。あなたの場合、 、 、 を置き換えると、が"a"として返されると仮定します。次に、怠惰に取り、使用して、が存在するかどうかを確認できます。"aa"n._2 + "a"makeSomeNetworkCall()tokenStringmaxTriestake(n)findexpectedToken

于 2013-11-07T22:18:48.200 に答える
1

mapon aRangeは怠惰ではないため、maxTriesネットワーク呼び出しを行い、結果を探しexpectedTokenます。代わりに、遅延構造を使用できます。Iteratorたとえば、次のとおりです。

Iterator.fill(maxTries) {
  makeSomeNetworkCall()
}.exists(_ == expectedToken)
于 2013-11-07T21:58:08.417 に答える