(1, 2, 3, 4, 5, 6)
- это 6-значный кортеж, который не имеет foldRight
, но Array(1, 2, 3, 4, 5, 6)
имеет.
ArrayLike
- это индексированные последовательности подклассов признаков с эффективным доступом к элементам, то есть оптимизированы определенные методы, в том числе, например, foldRight
. Каждый массив неявно преобразуется в подкласс черты ArrayLike
. Из багажника Скала:
@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)
Bytecode:
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; //InterfaceMethod scala/collection/SeqLike.apply:(I)Ljava/lang/Object;
22: aload_3
23: invokeinterface #72, 3; //InterfaceMethod scala/Function2.apply:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
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
на этом (последнее уже сделано). В случае всех последовательностей с эффективным произвольным доступом это поведение переопределяется и оптимизируется.