tl; dr: your method is loopcorrect, a link to the stream header will not be specified. You can test it on the infinite Stream.
Simplify your code example to the limit:
class Test {
private[this] var next: Test = _
final def fold(): Int = {
next = new Test
next.fold()
}
}
Note that your method is loopalso a method of some object.
The method final(just like Stream#foldLeft) is very important.
scalac -Xprint:all test.scala :
final def fold(): Int = {
<synthetic> val _$this: Test = Test.this;
_fold(_$this: Test){
({
Test.this.next = new Test();
_fold(Test.this.next)
}: Int)
}
};
, .
- - java.
: , method of object. "". this - . , , vtable, , .
, , : , .
, this - ( 0) .
- (javap -c Test.class):
public final int fold();
Code:
0: aload_0
1: new #2 // class Test
4: dup
5: invokespecial #16 // Method "<init>":()V
8: putfield #18 // Field next:LTest;
11: aload_0
12: getfield #18 // Field next:LTest;
15: astore_0
16: goto 0
- scala - :
static foo(var this: Test): Int {
:start
this.next = new Test
this = this.next
goto :start
}
this = this.next this . this GC!
, tail.foldLeft(...) Stream#foldLeft this = this.tail, ...; goto :start. this - @tailrec foldLeft.
scalac -Xprint:all test.scala:
final def method(a: A, b: B, ...): Res = {
<synthetic> val _$this: ThisType = ThisType.this;
_method(_$this: Test, a: A, b: B, ...){
({
_method(nextThis, nextA, nextB, ...)
}: Res)
}
};
:
final def method(var this: ThisType, var a: A, var b: B, ...): Res = {
:start
this = nextThis
a = nextA
b = nextB
...
goto :start
};
, scalac -Xprint:all loop, body . , :
...
case Some(x) =>
this = this
s = s.tail
acc = accumulate(x, acc)
goto :start
...
s = s.tail .