scala - 谓词成立时重复调用函数

标签 scala functional-programming

我正在向远程服务器发出请求,有时由于网络不可靠而导致请求失败。如果失败,我希望请求重复,但是 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)

最佳答案

规范的方法是使用 Iterator :

Iterator.continually{f}.take(nTries).dropWhile(!p).take(1).toList

它将为您提供一个空列表或一个单项列表,具体取决于它是否成功。您可以使用 headOption 将其转换为选项如果你愿意。稍加修改,这适用于您的所有用例。

像您所做的那样编写小的递归方法也是完全明智的,尽管它们不在库中。一般来说,为你最常做的事情编写辅助方法是一个很好的主意。这就是 Scala 使编写方法变得如此容易的原因之一。

关于scala - 谓词成立时重复调用函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11377586/

相关文章:

scala - 使用spark将数据写入cassandra

java - Scala/Java - 解析一些文本并删除标点符号的库?

scala - Scala 对象的初始化是如何工作的?

functional-programming - 学习函数式/Clojure 编程 - 实践练习?

javascript - 如何对数组中的对象使用 javascript reduce 函数来获取字符串值

haskell - 用于进度跟踪的 Monad 转换器

oop - 纯函数式编程上下文中的面向对象编程?

xml - 从 XML 中删除节点

ruby - open 关键字是 trait/mixin 吗?

javascript - 默认参数值未定义;这是一个 JavaScript 错误吗?