декоратор хвостовой рекурсии scala не позволяет вызывать рекурсивную функцию tail - PullRequest
0 голосов
/ 08 мая 2019
object FuncUtils {
  @tailrec
  def tryAll[T](funcs: (() => Any)*): Option[Any] = {
    if (funcs.isEmpty) {
      None
    } else {
      try {
        Some(funcs.head())
      } catch {
        case _: Throwable => FuncUtils.tryAll(funcs.tail: _*)
      }
    }
  }
}

Почему? Мне кажется, что tryAll самодостаточен, и итерация может происходить без ссылки на стек вызовов.

Ответы [ 2 ]

3 голосов
/ 08 мая 2019

Ошибка не воспроизводима, вы можете попытаться предоставить больше контекста.

В любом случае, я бы также рекомендовал вам не использовать Seq для хвостовых рекурсивных алгоритмов (вместо этого следует использовать List) и try / catch блоков (использовать Try Вместо монады) .
Это переписать ваш код, используя это.

import scala.util.{Try, Success, Failure}

object FuncUtils {
  def tryAll[T](funcs: (() => T)*): Option[T] = {
    @annotation.tailrec
    def loop(remaining: List[() => T]): Option[T] = remaining match {
      case Nil     => None
      case x :: xs => Try(x()) match {
        case Success(t) => Some(t)
        case Failure(_) => loop(remaining = xs)
      }
    }

    loop(remaining = funcs.toList)
  }
}

Опять же, как сказал jwvh, вам действительно не нужна рекурсия в этом случае.

object FuncUtils {
  def tryAll[T](funcs: (() => T)*): Option[T] =
    funcs.iterator.map(f => Try(f())).collectFirst { case Success(t) => t }
}
0 голосов
/ 08 мая 2019

Хорошо, причина в том, что я имею в виду объект Singleton, в котором содержится метод, перед вызовом функции.

 FuncUtils.tryAll(funcs.tail: _*)

Должно быть просто:

 tryAll(funcs.tail: _*)

Я полагаю, что Scala не может понять, что он рекурсивный, когда я ссылаюсь на библиотеку.

...