Last active
December 26, 2015 17:09
-
-
Save savelichalex/61527d8a5bf0bedfc966 to your computer and use it in GitHub Desktop.
Lazy Sequence and functions to work with this
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
/** | |
* Dalay expressions evaluation | |
* @param expressionAsFunc {Function} | |
* @returns {Function} thunk | |
*/ | |
function delay(expressionAsFunc) { | |
let result; | |
let isEvaluated = false; | |
return () => { | |
if (!isEvaluated) { | |
result = expressionAsFunc(); | |
} | |
return result; | |
} | |
} | |
/** | |
* Force thunk to evaluate | |
* @param thunk {Function} | |
* @returns {*} evaluated expression | |
*/ | |
function force(thunk) { | |
return thunk(); | |
} | |
/** | |
* Create cons | |
* @param car {*} | |
* @param cdr {Function} | |
* @returns {*[]} | |
*/ | |
function cons(car, cdr) { | |
return [car, cdr]; | |
} | |
/** | |
* Create a sequence cons pair | |
* @param x {*} cons car | |
* @param y {*} cons cdr | |
*/ | |
function seqCons(x, y) { | |
return cons(x, delay(y)); | |
} | |
/** | |
* Return car of sequence | |
* @param seq {Sequence} | |
*/ | |
function seqCar(seq) { | |
return seq[0]; | |
} | |
/** | |
* Return cdr of sequence | |
* @param seq {Sequence} | |
*/ | |
function seqCdr(seq) { | |
return force(seq[1]); | |
} | |
/** | |
* Empty seq | |
*/ | |
const theEmptySeq = []; | |
/** | |
* Function to check that seq is empty | |
* @param seq {Sequence} | |
* @return {boolean} | |
*/ | |
function seqNull(seq) { | |
return seq.length === 0; | |
} | |
/** | |
* Ref function | |
* @param seq {Sequence} | |
* @param n {number} | |
*/ | |
function seqRef(seq, n) { | |
if (n === 0) { | |
return seqCar(seq); | |
} else { | |
return seqRef(seqCdr(seq), n - 1); | |
} | |
} | |
/** | |
* Return result of apply proc to each item in sequence s | |
* @param proc {Function} | |
* @param s {Sequence} | |
*/ | |
function seqMap(proc, s) { | |
if (seqNull(s)) { | |
return theEmptySeq; | |
} else { | |
return seqCons(proc(seqCar(s)), () => seqMap(proc, seqCdr(s)) | |
) | |
; | |
} | |
} | |
/** | |
* Apply procedure to each item in sequence s | |
* @param procedure {Function} | |
* @param s {Sequence} | |
*/ | |
function seqForEach(procedure, s) { | |
if (seqNull(s)) { | |
return; | |
} else { | |
procedure(seqCar(s)); | |
return seqForEach(procedure, seqCdr(s)); | |
} | |
} | |
/** | |
* Folter sequence by predicate | |
* @param predicate {Function} | |
* @param seq {Sequence} | |
* @returns {*} | |
*/ | |
function seqFilter(predicate, seq) { | |
if (seqNull(seq)) { | |
return theEmptySeq; | |
} else { | |
const car = seqCar(seq); | |
if (predicate(car)) { | |
return seqCons(car, () => seqFilter(predicate, seqCdr(seq)) | |
) | |
; | |
} else { | |
return seqFilter(predicate, seqCdr(seq)); | |
} | |
} | |
} | |
function seqTake(seq, n) { | |
if (n === 1) { | |
return seqCons(seqCar(seq), () => theEmptySeq); | |
} else { | |
return seqCons(seqCar(seq), () => seqTake(seqCdr(seq), n - 1)); | |
} | |
} | |
/** | |
* Create sequence in range between low and high | |
* @param low {number} | |
* @param high {number} | |
* @returns {*} | |
*/ | |
function range(low, high) { | |
if (low > high) { | |
return theEmptySeq; | |
} else { | |
return seqCons(low, () => range(low + 1, high)); | |
} | |
} | |
console.log('Lazy evaluation'); | |
var multiplyCount = 0; | |
function multiplyByTwo(val) { | |
multiplyCount++; | |
return val * 2; | |
} | |
var oddCount = 0; | |
function odd(val) { | |
oddCount++; | |
return val % 10 === 0; | |
} | |
var logCount = 0; | |
function log(val) { | |
logCount++; | |
console.log(val); | |
} | |
var startTime; | |
var endTime; | |
startTime = Date.now(); | |
seqForEach( | |
log, | |
seqTake( | |
seqMap( | |
multiplyByTwo, | |
seqFilter( | |
odd, | |
range(1, 1000) | |
) | |
), | |
5 | |
) | |
); | |
endTime = Date.now(); | |
console.log(['Odd called ', oddCount, ' times\n', | |
'Multiply called ', multiplyCount, ' times\n', | |
'Log called ' + logCount + ' times\n', | |
'Time: ', endTime - startTime, '\n'].join('')); | |
console.log('Native evaluation'); | |
multiplyCount = 0; | |
oddCount = 0; | |
logCount = 0; | |
var arr = []; | |
for(var i = 1; i < 1001; i++) { | |
arr.push(i); | |
} | |
startTime = Date.now(); | |
arr.filter(odd).map(multiplyByTwo).slice(0, 5).forEach(log); | |
endTime = Date.now(); | |
console.log(['Odd called ', oddCount, ' times\n', | |
'Multiply called ', multiplyCount, ' times\n', | |
'Log called ' + logCount + ' times\n', | |
'Time: ', endTime - startTime, '\n'].join('')); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment