【问题标题】:Scala Transform recursive function with a map inside to tail recursionScala将递归函数与内部映射转换为尾递归
【发布时间】:2017-04-29 03:06:29
【问题描述】:

我有一个对象,我们称它为 RT,它有两个字段:一个字符串和一个自身的 List。

def case class RT[String](topic: String, children: List[RT[String]])

现在我有了以下递归函数:

def func(tree: RT[String]): List[String] = {
  tree.children match  {
    case Nil=> List(tree.topic)
    case child =>
      val subTrees = child.map(rt => func(rt))
      subTrees.foldLeft(List(tree.topic))((acc,list) => acc ::: list ::: List(tree.topic))
  }
}

这让我得到了我想要的。但是,在非常嵌套的情况下,我得到了一个 StackOverflow,所以我希望将前面的函数转换成它的尾递归形式。但是,我看不出如何。有可能吗?

【问题讨论】:

  • 虽然您的问题在技术上不是重复的,但如果您阅读过this question,您就不需要问了。
  • @Malvolio 仍然没有解决我的问题。

标签: scala recursion tail-recursion map-function


【解决方案1】:

首先,让我简化你的原始代码,很多:

case class RT(topic: String, children: List[RT])

def func(tree: RT): List[String] =
  tree.topic :: tree.children.flatMap(rt => func(rt))

(借用 Inigo Montoya,我不认为 case class RT[String] 意味着你认为的意思。它不是以某种方式构建在 Scala 字符串上的参数化类。它是构建在任意类型上的参数化类您正在调用“String”,尽管它不一定具有任何类似字符串的特性。稍后,您将使用真正的字符串实例化类型类。)

它仍然不是尾递归的,所以让我们玩通常的把戏:

def func(tree: RT): List[String] = {
  @tailrec
  def funcAcc(trees: List[RT], acc: List[String]): List[String] = {
    if (trees.isEmpty)
      acc
    else
      funcAcc(trees.tail ::: trees.head.children, trees.head.topic :: acc)
  }
  funcAcc(List(tree), Nil).reverse
}

那里,行得通。

(我们本可以避免使用reverse,但这需要追加到不断增长的列表中,并且一大堆追加通常比相同数量的前置要慢得多,然后反过来。)

【讨论】:

  • “它是一个类型类”。它不是类型类。这是一堂课。一个案例类。但不是类型类。
  • @pedrofurla - 我在 Scala 中找不到类型类的正式定义。所有类型类都是参数化类,但所有参数化类都是类型类吗?
  • @Malvolio 你运行我的代码了吗?您是否意识到使用您的解决方案并没有得到相同的结果?
  • @Alessandroempire - 您要求退款吗?
猜你喜欢
  • 1970-01-01
  • 2016-01-06
  • 2019-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多