-
Notifications
You must be signed in to change notification settings - Fork 571
Open
Description
TCO outputs a while loop that calls a function on every iteration, incurring a performance penalty.
An example. Here is the definition of tailRec from purescript-tailrec:
tailRec :: forall a b. (a -> Step a b) -> a -> b
tailRec f = go <<< f
where
go (Loop a) = go (f a)
go (Done b) = bIt compiles to the following:
var tailRec = function (f) {
var go = function ($copy_v) {
var $tco_done = false;
var $tco_result;
function $tco_loop(v) {
if (v instanceof Loop) {
$copy_v = f(v.value0);
return;
};
if (v instanceof Done) {
$tco_done = true;
return v.value0;
};
throw new Error("Failed pattern match at Control.Monad.Rec.Class line 96, column 3 - line 96, column 25: " + [ v.constructor.name ]);
};
while (!$tco_done) {
$tco_result = $tco_loop($copy_v);
};
return $tco_result;
};
return function ($53) {
return go(f($53));
};
};In this case, and many others, the $tco_loop function could be inlined into the while loop, simplifying the resulting code and improving its performance.
To be sure, I imagine the TCO behavior was initially created this way with good reason, so there might be some situation where we can't safely get rid of the closure. We should seek to document this.