z66is

HELLO JAVASCRIPT

Jul 7th, 2026
13,171
0
Never
1
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // trampoline : (thunk -> thunk | value) -> value
  2. // Runs a chain of thunks iteratively so recursion doesn't grow the JS call stack.
  3. // - Start with a "thunk" (a function with no args)
  4. // - While the result is still a function, keep calling it
  5. // - When a non-function value is produced, return it
  6. const trampoline = (thunk) => {
  7.   let t = thunk;
  8.   while (typeof t === "function") t = t(); // keep "bouncing"
  9.   return t; // final value
  10. };
  11.  
  12. // foldl : (f, acc, xs, k) -> ...
  13. //
  14. // Fold an array xs from left to right in a continuation-passing style (CPS) and
  15. // use trampoline to stay stack-safe.
  16. //
  17. // Type-ish comments:
  18. // - f : (x, acc, k2) => ...
  19. //   where k2 : (newAcc) => ... is a continuation that tells foldl what to do next
  20. //   IMPORTANT: f is expected to call k2(newAcc) rather than directly returning newAcc.
  21. // - k : (finalAcc) => ... is the final continuation invoked at the end.
  22. //
  23. // Returns: a call that eventually triggers k(finalAcc).
  24. const foldl = (f, acc, xs, k) => {
  25.   // step(i, accNow) describes "the rest of the fold" starting at index i
  26.   // and current accumulator accNow.
  27.   //
  28.   // It returns either:
  29.   // - a thunk (function) that when called computes the next step, or
  30.   // - in the base case, a thunk that calls k(accNow).
  31.   const step = (i, accNow) => {
  32.     // Base case: we've processed every element in xs.
  33.     if (i >= xs.length) return () => k(accNow);
  34.  
  35.     // Process the next element.
  36.     const x = xs[i];
  37.  
  38.     // We don't call f(x, accNow, ...) immediately on the call stack.
  39.     // Instead, we return a thunk so trampoline can manage the iteration safely.
  40.     return () =>
  41.       // Call f in CPS form:
  42.       // f decides how to compute/update the accumulator, and then calls k2(newAcc).
  43.       f(x, accNow, (newAcc) => {
  44.         // After f computes newAcc, continue folding from i+1.
  45.         // step(i + 1, newAcc) returns a thunk, which trampoline will eventually run.
  46.         return step(i + 1, newAcc);
  47.       });
  48.   };
  49.  
  50.   // Start the fold at index 0 with the initial accumulator acc.
  51.   // step(0, acc) returns the initial thunk; trampoline runs it to completion.
  52.   return trampoline(() => step(0, acc));
  53. };
Advertisement