我对scala尾递归有疑问。我写了一个简单的尾递归代码,它接受一个列表并创建一个偶数的新列表。但由于scala无法将元素追加到列表中,因此我的列表按降序排序。以下是代码
def listCreator(lists: List[Int]): List[Int] = {
@tailrec
def evenListCreator(lists: List[Int], accum: List[Int]): List[Int] = {
lists match {
case Nil => accum
case x :: Nil if (isEven (x) == true) => x :: accum
case x :: Nil if (isEven (x) == false) => accum
case x :: tail if (isEven (x) == true) => evenListCreator(tail, x :: accum)
case x :: tail if (isEven (x) == false) => evenListCreator(tail, accum)
}
}
evenListCreator(lists, List())
}
我有以下问题
如何在此方法中添加反转列表的语句?
紧跟在方法调用之后的这一行evenListCreator(lists, List())
是尾递归必需的吗?
答案 0 :(得分:2)
你可以在返回之前撤消。
scala> def listCreator(lists: List[Int]): List[Int] = {
| @tailrec
| def evenListCreator(lists: List[Int], accum: List[Int]): List[Int] = {
| lists match {
| case Nil => accum
| case x :: Nil if (isEven (x) == true) => x :: accum
| case x :: Nil if (isEven (x) == false) => accum
| case x :: tail if (isEven (x) == true) => evenListCreator(tail, x :: accum)
| case x :: tail if (isEven (x) == false) => evenListCreator(tail, accum)
| }
| }
| evenListCreator(lists, List.empty[Int]).reverse
| }
listCreator: (lists: List[Int])List[Int]
scala> listCreator((1 to 10).toList)
res2: List[Int] = List(2, 4, 6, 8, 10)
scala>
您不需要立即跟随方法调用,但如果不这样做,则需要发送两个参数,一个是列表,第二个是空列表。因此我们只采用整数列表,以便正在使用的人也不必像发送空列表一样烦恼。
你也可以直接这样做
scala> val list = (1 to 10).toList
list: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
scala> list.map(_ * 2)
res8: List[Int] = List(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)
scala>
答案 1 :(得分:2)
evenListCreator(lists, List()).reverse
或evenListCreator(lists.reverse, List())
,但在您的情况下,第一种形式更好,因为在调用evenListCreator
evenListCreator(lists, List())
不遵循方法调用, 方法调用。没有它,没有任何事情会发生,因为你只定义你的尾递归函数(def evenListCreator
)并在不调用它的情况下返回。其他一些说明
你有太多停止条件,这就足够了:
@tailrec
def evenListCreator(lists: List[Int], accum: List[Int]): List[Int] = {
lists match {
case Nil => accum
case x :: tail if (isEven (x) == true) => evenListCreator(tail, x :: accum)
case x :: tail if (isEven (x) == false) => evenListCreator(tail, accum)
}
}
代码太冗长,我认为这样更好:
@tailrec
def evenListCreator(lists: List[Int], accum: List[Int]): List[Int] = {
lists match {
case Nil => accum
case x :: tail if isEven (x) => evenListCreator(tail, x :: accum)
case x :: tail if !isEven (x) => evenListCreator(tail, accum)
}
}
你也可以这样调用递归函数:
evenListCreator(lists, Nil)
答案 2 :(得分:2)
Q1。你可以在@Mahesh Chand Kandpal指出之前反转List
,或者你可以使用追加方法accum :+ x
来构建列表,而不是预先挂起(&#34) ; cons")方法,x :: accum
。
但是在List
上,cons方法比append方法更有效,因此构建和反转通常更好。
Q2。不会。尾递归只是意味着在调用返回后没有其他操作等待。换句话说,return callMyself()
是尾调用,但return callMyself() + 1
不是。
P.S。我知道这只是一次学习练习,但是,真的......
def listCreator(ints: List[Int]): List[Int] = ints.filter(i => (i&1) < 1)