JS lane: List.length over a long list dies with a stack overflow (the base recursion is not in tail position); a tail counter over the same list completes
What you did
A 200,000-element list (built by a tail-recursive helper, no large literals), counted two ways:
bend llist.bend(JS lane),List.lengthbend llist.bend -o llist && ./llist(native C lane)- same with an inner tail counter instead of
List.length
What happened
JS lane, List.length:
bend: memory fault (machine stack overflow?)JS lane, tail counter over the same list: len=200000. Native, both: len=200000.
Threshold on the JS lane: 10,000 elements count fine, 50,000 fails. Base.List.length is not tail-recursive (1n+List.length(a, A, t), bend2/base.bend:742-747 at 0b7e2b11), so the emitted JS keeps one frame per element. Same class as #798 for String.split/String.length (which is why our parser lane avoids it with a counter), but this is the List helper. Reproduces on 2.0.4 and 2.0.5.
The file
import Base
def gen(n: Nat, acc: List<&2, U32>) -> List<&2, U32>:
match n:
case 0n:
acc
case 1n+p:
gen(p, 1 <> acc)
def main() -> IO(Unit):
do IO<Unit>:
IO.print("len=" ++ Nat.show(List.length(&2, U32, gen(Nat.mul(100n, 2000n), Nil{}))))The counter variant replaces List.length(...) with count.go(gen(...), 0n); count.go is Nil{} -> n; h <> t -> count.go(t, 1n+n).
bend --version
bend 2.0.5 (2.0.4 the same)
uname -sm
Linux x86_64
clang --version (the first line)
clang version 21.1.7 (Fedora 21.1.7-1.fc43)
Source: HigherOrderCO/Bend