RationalJS/future

Flat map is not stack safe.

Closed this issue · 1 comments

When writing recursive functions using flatMap a program can crash with maximum call stack error:

let next = x => Future.value(x + 1);
let numberOfLoops = 10000;
let rec loop = x => {
  next(x)
  ->Future.flatMap(x' =>
      if (x' == numberOfLoops) {
        Future.value(x');
      } else {
        loop(x');
      }
    );
};
loop(0)
    RangeError: Maximum call stack size exceeded

      17 |           } else {
      18 |             data[0] = Caml_option.some(result);
    > 19 |             Belt_List.forEach(Belt_List.reverse(callbacks[0]), (function (cb) {
         |                       ^
      20 |                     return Curry._1(cb, result);
      21 |                   }));
      22 |             callbacks[0] = /* [] */0;

      at forEachU (node_modules/bs-platform/lib/js/belt_List.js:785:18)
      at Object.forEach (node_modules/bs-platform/lib/js/belt_List.js:799:10)
      at src/Future.bs.js:19:23
      at Object._1 (node_modules/bs-platform/lib/js/curry.js:65:12)
      at src/Future.bs.js:42:30
      at Object._1 (node_modules/bs-platform/lib/js/curry.js:65:12)
      at make (src/Future.bs.js:13:9)
      at Object.value (src/Future.bs.js:41:10)
      at loop (__tests__/TestFuture.bs.js:364:54)
      at __tests__/TestFuture.bs.js:368:48

See #44 for an attempted fix.

Addressed in #44