【问题标题】:scala: make a function tail recursivescala:使函数尾递归
【发布时间】:2019-11-29 19:26:02
【问题描述】:

我在scala中有以下功能:

def is_in[T](e: T, as: List[T]) : Boolean = as match
{
  case Nil => false;
  case x::xs => e == x || is_in(e, xs);
}

现在我想让这个函数尾递归。我的想法如下:

// tail recursive:

def is_in[T](e: T, as:List[T]) : Boolean =
{
  @tailrec
  def is_in_tailrec[T](e: T, as:List[T], acc: Boolean) : Boolean =
  {
    as match
    {
      case Nil => acc;
      case x::xs => is_in_tailrec(... here I got stuck ...);
    }
  }
  is_in_tailrec(e, as, 1);
}

谁能给我一个建议,我怎样才能使这个函数尾递归?

【问题讨论】:

  • 已经是尾递归了。

标签: scala tail-recursion


【解决方案1】:

其实这里不需要带累加器的辅助方法。只需检查e == x 是否返回false,然后与列表的其余部分一起调用该方法,否则返回true:

  def is_in[T](e: T, as: List[T]): Boolean = as match {
    case Nil => false
    case x :: _ if e == x => true
    case _ :: xs => is_in(e, xs)
  }

【讨论】:

  • 你甚至不需要这样做,这个函数已经是尾递归了。
【解决方案2】:

您的函数已经是尾递归的。如果你把它标记为@annotation.tailrec,它编译就好了。

【讨论】:

    【解决方案3】:

    我的建议是

    {
        case Nil => acc
        case _ if acc => acc
        case x :: xs => is_in_tailrec(e, xs, x == e)
    }
    

    甚至可能是

    {
        case x :: xs if !acc => is_in_tailrec(e, xs, x == e)
        case _ => acc
    }
    

    【讨论】:

    • 我想知道为什么使用类似于我的版本的帮助方法发布答案的人删除了他的帖子。我只是想分析一下,看看我的错误是什么......
    • @seas 在他的版本 acc 中总是错误的,也许他意识到了 - 这就是为什么......这个也是你的版本,我只是部分公开了它
    【解决方案4】:

    我想知道为什么使用类似于我的版本的帮助方法发布答案的人删除了他的帖子。我只是想分析一下,看看我的错误是什么......

    我猜你是说

    def is_in[T](e: T, as: List[T]) : Boolean = {
      @tailrec
      def is_in_tailrec[T](e: T, as: List[T], acc: Boolean): Boolean = as match {
        case Nil     => acc
        case x :: xs => is_in_tailrec(e, xs, e == x || acc)
      }
    
      is_in_tailrec(e, as, false)
    }
    

    由于is_in_tailrec 中的Te 始终与is_in 中的Te 相同,因此可以将其重写为

    def is_in[T](e: T, as: List[T]) : Boolean = {
      @tailrec
      def is_in_tailrec(as: List[T], acc: Boolean): Boolean = as match {
        case Nil     => acc;
        case x :: xs => is_in_tailrec(xs, e == x || acc)
      }
    
      is_in_tailrec(as, false)
    }
    

    【讨论】:

    • 在您的第一次发布中,您最后有以下行... is_in_tailrec(e, as, false)。这是为了初始化目的吗?我的想法是 acc 在这一行的开头被初始化为 false 。然后可能会发生列表一开始是空的,这意味着立即返回 false 或者列表不为空,然后检查是否 e == x,如果是,则返回 true,如果不是,我们有初始化中的错误。因此,如果我们要查找的元素最终不在列表中,则返回 false。这是正确的吗?
    • 我的想法在我之前的评论中是正确的还是我错过了什么?
    猜你喜欢
    • 1970-01-01
    • 2018-03-17
    • 1970-01-01
    • 2018-03-08
    • 2021-01-25
    • 2017-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多