How do I replace while loops with a functional programming alternative without tail call optimization?
An example in JavaScript
Here's an example using JavaScript. Currently, most browsers do not support tail call optimisation and therefore the following snippet will fail
const repeat = n => f => x => n === 0 ? x : repeat (n - 1) (f) (f(x)) console.log(repeat(1e3) (x => x + 1) (0)) // 1000console.log(repeat(1e5) (x => x + 1) (0)) // Error: Uncaught RangeError: Maximum call stack size exceeded
While or Tail Recursion in F#, what to use when?
The best answer is 'neither'. :)
There's some ugliness associated with both while loops and tail recursion.
While loops require mutability and effects, and though I have nothing against using these in moderation, especially when encapsulated in the context of a local function, you do sometimes feel like you're cluttering/uglifying your program when you start introducing effects merely to loop.
Tail recursion often has the disadvantage of requiring an extra accumulator parameter or continuation-passing style. This clutters the program with extra boilerplate to massage the startup conditions of the function.
The best answer is to use neither while loops nor recursion. Higher-order functions and lambdas are your saviors here, especially maps and folds. Why fool around with messy control structures for looping when you can encapsulate those in reusable libraries and then just state the essence of your computation simply and declaratively?
If you get in the habit of often calling map/fold rather than using loops/recursion, as well as providing a fold function along with any new tree-structured data type you introduce, you'll go far. :)
For those interested in learning more about folds in F#, why not check out my first three blog posts in a series on the topic?
How to implement an infinite update loop in a functional way
If there was a tail recursion optimization, the generated code would be very similar to something like
void RunUpdateLoop(WorldState world) {
while(1) { world = RunUpdateLoop(world); }
}
No?
Of course you could say that's not "functional" enough, but you're asking for a "functional" solution in a procedural language. So, not quite sure what you are after.
You can always simulate a call stack in the heap with a stack-like data structure, and do the tail-recursion optimization yourself, but in this case it will once again collapse to something very similar to the above.
While or Tail Recursion in F#, what to use when?
The best answer is 'neither'. :)
There's some ugliness associated with both while loops and tail recursion.
While loops require mutability and effects, and though I have nothing against using these in moderation, especially when encapsulated in the context of a local function, you do sometimes feel like you're cluttering/uglifying your program when you start introducing effects merely to loop.
Tail recursion often has the disadvantage of requiring an extra accumulator parameter or continuation-passing style. This clutters the program with extra boilerplate to massage the startup conditions of the function.
The best answer is to use neither while loops nor recursion. Higher-order functions and lambdas are your saviors here, especially maps and folds. Why fool around with messy control structures for looping when you can encapsulate those in reusable libraries and then just state the essence of your computation simply and declaratively?
If you get in the habit of often calling map/fold rather than using loops/recursion, as well as providing a fold function along with any new tree-structured data type you introduce, you'll go far. :)
For those interested in learning more about folds in F#, why not check out my first three blog posts in a series on the topic?
Can fix be tail recursive and thus expressed as a simple loop?
I can't figure out how to express
fix
as a tail recursive algorithm.
First, convert the definition of fix
into A-normal form.
// fix :: ((a -> b) -> a -> b) -> a -> b
const fix = f => x => {
const g = fix(f);
const h = f(g);
const y = h(x);
return y;
};
Next, convert the resulting program into continuation-passing style.
// type Cont r a = (a -> r) -> r
// fix :: ((a -> Cont r b) -> Cont r (a -> Cont r b)) -> Cont r (a -> Cont r b)
const fix = f => k => k(x => k =>
fix(f) (g =>
f(g) (h =>
h(x) (y =>
k(y)))));
Now, fix
is tail recursive. However, this is probably not what you want.
A tail recursive algorithm could be easily transformed to a stack safe loop. That is the actual goal.
If all you want is stack safety, then you could use the Trampoline
monad.
// Bounce :: (a -> Trampoline b) -> a -> Trampoline bconst Bounce = func => (...args) => ({ bounce: true, func, args });
// Return :: a -> Trampoline aconst Return = value => ({ bounce: false, value });
// trampoline :: Trampoline a -> aconst trampoline = result => { while (result.bounce) result = result.func(...result.args); return result.value;};
// fix :: ((a -> Trampoline b) -> a -> Trampoline b) -> a -> Trampoline bconst fix = f => Bounce(x => f(fix(f))(x));
// id :: a -> aconst id = x => x;
// reachable codeconsole.log("begin"); // open the console in your browser
// infinite looptrampoline(fix(id)(0));
// unreachable codeconsole.log("end");
Is there a way to call a function without adding to the call stack?
My solution is to write an exec()
routine that stops the recursion:
template<typename Func>
void exec(const Func& f)
{
using function_t = Func;
static std::map<const function_t*, size_t> functions;
const auto it = functions.find(&f);
if (it == functions.end())
{
functions[&f] = 1;
while (functions[&f] > 0)
{
f();
functions[&f]--;
}
functions.erase(&f);
}
else
{
functions[&f]++;
}
}
With that utility, I can more-or-less preserve the appearance of the existing code
class test4 final
{
int i = 0;
void goto_loop_() {
i++;
if (i > 10) goto_done(); }
void goto_loop() { goto_loop_(); static const auto f = [&]() { goto_loop(); }; exec(f); }
void goto_done()
{
exit(EXIT_SUCCESS);
}
public:
test4() { goto_loop(); }
};
(Using a lambda avoids hassles with pointers to members functions.)
how to call a function and use a global variable in that function
I'm not sure how to use
n
in loop function.
You can't, that what makes nested function definitions so popular :-) You would need to add a fourth parameter, and pass that through all of your recursive calls unaltered:
let rec loop i n a b =
if i = n then a
else loop (i+1) (n) (b) (a+b)
let fib n =
loop 0 n 0 1
Alternatively, you change the looping structure so that it doesn't count i
up from 0
to n
, but rather have a variable (say j
) count down from n
so you only need to check when it reaches 0
in loop
:
let rec loop j a b =
if j = 0 then a
else loop (j-1) (b) (a+b)
let fib n =
loop n 0 1
Related Topics
Underscore Template Throwing Variable Not Defined Error
What's Wrong with Awaiting a Promise Chain
Constructor Function VS Factory Functions
How to Redirect with JavaScript
JavaScript - Href VS Onclick for Callback Function on Hyperlink
Warn User Before Leaving Web Page with Unsaved Changes
Babel File Is Copied Without Being Transformed
Why Doesn't Equality Check Work with Arrays
Is JavaScript Supported in an Email Message
How to Fix Error: Listen Eaddrinuse While Using Nodejs
How to Refresh a Page Using JavaScript
Difference Between Microtask and MACrotask Within an Event Loop Context
Why Are Callbacks from Promise '.Then' Methods an Anti-Pattern
Is There a Null-Coalescing (Elvis) Operator or Safe Navigation Operator in JavaScript