apple / apple/pkl

Using `fold()` and `reduce()` to compose objects creates deep call stacks

Open
#977 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
11.5k
Forks
402
Avg merge
1d 15h
Merged PRs (30d)
20

Description

This code will stack overflow:

```pkl
class Num {
value: Int
}

local numbers: List = IntSeq(0, 100000).map((i) -> new Num { value = i })

local adder = (numA: Num, numB: Num) -> new Num { value = numA.value + numB.value }

sum = numbers.reduce(adder).value
```

At the end of each iteration, the returned value from `adder` retains a lazy `value`. The resulting object, as a result, has a `value` member that recurses.

This type of code is less performant, and is also vulnerable to stack overflow exceptions. It's also very hard to understand why this is recursive. We should have some way to avoid deep call stacks here.

Note: a workaround is to force the computation with a `let` expression, e.g.

```pkl
local adder = (numA: Num, numB: Num) ->
let (result = numA.value + numB.value)
new Num { value = result }
```

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the provided `reduce()` example with 100,000 `Num` values and compare it with the `let` workaround. Read the evaluation behavior around lazy `value` members and the `fold()`/`reduce()` operations. Done means object composition avoids recursive call stacks while preserving the computed result.

Written by the indexing model from the issue text.

Assessment

Domain
compilers
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.