(1, 2, 3, 4, 5, 6)
是一个6个值的元组,它没有foldRight
方法,但Array(1, 2, 3, 4, 5, 6)
有这个方法。
ArrayLike
是一个子类化索引序列并具有高效元素访问的特质,这意味着它有某些被优化的方法,包括例如foldRight
。每个数组都会隐式地转换为ArrayLike
特质的子类。来自Scala trunk:
@tailrec
private def foldr[B](start: Int, end: Int, z: B, op: (A, B) => B): B =
if (start == end) z
else foldr(start, end - 1, op(this(end - 1), z), op)
字节码:
private static java.lang.Object foldr(scala.collection.IndexedSeqOptimized, int, int, java.lang.Object, scala.Function2);
...
Code:
Stack=6, Locals=6, Args_size=5
0: iload_1
1: iload_2
2: if_icmpne 7
5: aload_3
6: areturn
7: aload_0
8: iload_2
9: iconst_1
10: isub
11: aload 4
13: aload_0
14: iload_2
15: iconst_1
16: isub
17: invokeinterface #21, 2;
22: aload_3
23: invokeinterface #72, 3;
28: astore_3
29: istore_2
30: astore_0
31: goto 0
LineNumberTable:
line 68: 0
line 67: 6
line 69: 7
编辑:字节码中的方法是迭代的,这意味着编译器必须应用尾调用优化。
若没有有效的元素访问方式(如有效的apply
方法),通常情况下最好的做法是使用迭代器和非尾递归函数实现foldRight
,或通过构建一个新集合来反转集合并在其上执行foldLeft
(目前采用后一种方式)。对于所有具有有效随机访问的序列,将覆盖并进行了优化。
foldRight
和reduceRight
实际上是尾递归的。它们基本上被转化为一个foldLeft
,只不过索引的变化方向相反。 - huynhjl(1,2,3,4,5,6)
是元组,而不是数组。如果您想要一个数组,请使用Array(1,2,3,4,5,6)
来调用它。其他人已经回答了一些有趣的算法问题。 - Rex Kerr