Skip to content

Instantly share code, notes, and snippets.

@candyapplecorn
Forked from kana/lazy.js
Last active May 13, 2017 07:42
Show Gist options
  • Save candyapplecorn/733e740a0dc3b2ba55b72405b884a7fe to your computer and use it in GitHub Desktop.
Save candyapplecorn/733e740a0dc3b2ba55b72405b884a7fe to your computer and use it in GitHub Desktop.
Lazy evaluation in JavaScript
function delay(expressionAsFunction) {
var result;
var isEvaluated = false;
return function () {
if (!(isEvaluated || ((isEvaluated = true), false)))
result = expressionAsFunction();
return result;
};
}
function force(promise) {
return promise();
}
function cons(car, cdr) {
return [car, cdr];
}
function next(n) {
return cons(n, delay(function () {return next(n + 1);}));
}
function head(stream) {
return stream[0];
}
function tail(stream) {
return force(stream[1]);
}
var stream = next(0);
console.log(stream);
console.log(head(tail(tail(stream)))); //==> 2
@candyapplecorn
Copy link
Author

candyapplecorn commented Jun 18, 2016

The local variable isEvaluated inside of delay wasn't changing state, and I wanted to fix that bug while not adding any extra lines of code.

At first I went with a solution where I initialized isEvaluated to 0, and then checked the truthiness of isEvaluated++. That solution yielded the desired functionality, but hypothetically was prone to a bug where isEvaluated could exceed the maximum value for an integer.

My new solution takes advantage of logical or and comma operators; thanks to short-circuiting, this solution should be fast as it will just return isEvaluated (when isEvaluated is true) without executing the logical or's right operand. The right operand assigns isEvaluated true, an expression which then evaluates to true - but thanks to the comma operator, the code "forcibly" returns false, which is the desired value; that is, the evaluated expression should differ in truthiness from all subsequent evaluations.

@Jomik
Copy link

Jomik commented May 13, 2017

How about if (!(isEvaluated || !(isEvaluated = true))) rather than the , false "hack".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment