【问题标题】:Scala Non-Tail Recursive Solution [duplicate]Scala非尾递归解决方案[重复]
【发布时间】:2023-04-03 23:20:01
【问题描述】:

我有这个尾递归函数,如果列表中的任何元素是 Boolean 值,则返回 true。

def anyBoolTailRec[A](test: A=> Boolean, a: List[A]): Boolean = a match {
    case Nil => false
    case h :: t if(!test(h)) => anyBoolTailRec(test, t)
    case _ => true
}

测试参数只是一个检查值类型的函数:

def isBool(i: Any) = i match {
    case _: Boolean => true
    case _    => false
}

函数是这样调用的:

anyBoolTailRec(isBool, List(1, 2, "hi", "test", false))
>>> true

问题:我怎样才能把这个尾递归解决方案变成一个非尾递归解决方案?由于我们要返回布尔值,我不知道该怎么做。

注意:我知道尾递归解决方案在 Scala 中更好。

【问题讨论】:

  • 将第二行改为case h :: t if(!test(h)) => val foo = anyBoolTailRec(test, t); foo 下一个问题是如何让它成指数增长?
  • 如何让它指数化?不,我只是想知道如何将我的功能更改为非尾解决方案。布尔返回值让我失望。我习惯于做类似 foo(test, t + 1)
  • 你为什么要问两次?你已经问过这个话题:stackoverflow.com/questions/46598594/…

标签: scala recursion


【解决方案1】:

没有理由这样做。你只是让你的代码变得更糟而没有任何好处,但是......

将尾递归解决方案转换为非尾递归解决方案很容易。您可以只添加一些不影响结果的操作,以便递归调用不再处于尾部位置。一个始终有效的简单解决方案是在返回之前将递归调用的结果存储在局部变量中。

def anyBoolTailRec[A](test: A=> Boolean, a: List[A]): Boolean = a match {
    case Nil => false
    case h :: t if(!test(h)) => val foo = anyBoolTailRec(test, t); foo
    case _ => true
}

【讨论】:

  • 有道理!谢谢。但是,由于我们在第二行使用|| false 评估 false,是否还需要 case Nil?
  • @Phillip 是的,如果没有 Nil => false 的情况,Nil 将评估为 true,因为它与模式 h :: t 不匹配,它将属于默认情况 _ => true
  • @Phillip Dima 的评论提供了一个更通用的解决方案,适用于任何数据类型,而我的仅适用于布尔值,我将编辑我的答案以包含他的方法。
猜你喜欢
  • 2020-07-13
  • 1970-01-01
  • 1970-01-01
  • 2018-03-17
  • 2013-08-31
  • 1970-01-01
  • 1970-01-01
  • 2013-07-22
  • 1970-01-01
相关资源
最近更新 更多