Last active
June 24, 2024 13:20
-
-
Save ankithooda/6313a460679b080c0f045a68180a53db to your computer and use it in GitHub Desktop.
Infinite Stream Objects in Javascript
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
//Infinite steams implemented in Javascript as described in Chapter 3 of SICP. | |
////////////////////////////// Start of Program /////////////// | |
// This is cons function of lisp | |
function pair(a, b) { | |
return [a, b]; | |
} | |
// this is car function of lisp | |
function first(a) { | |
return a[0]; | |
} | |
// this is cdr function of lisp | |
function rest(a) { | |
return a[1]; | |
} | |
// Implementation of delay & force. | |
function delay(exp) { | |
return function() { | |
return exp(); | |
} | |
} | |
function force(promise) { | |
return promise(); | |
} | |
function stream_pair(a, b) { | |
// every call of stream pair wrap the cdr argument in a zero argument function. | |
return pair(a, delay(b)); | |
} | |
// stream equivalent of car | |
function stream_first(stream) { | |
return first(stream); | |
} | |
// stream equivalent of cdr | |
function stream_rest(stream) { | |
return force(rest(stream)); | |
} | |
function empty_stream() { | |
return []; | |
} | |
function is_stream_empty(stream) { | |
return !stream || stream.length === 0; | |
} | |
// execute proc function for len elements in the infinite steam | |
function stream_map_len(proc, len, stream) { | |
if (is_stream_empty(stream)) { | |
return empty_stream; | |
} else { | |
if (len != 0) { | |
return stream_pair( | |
proc(first(stream)), | |
stream_map_len(proc, len - 1, stream_rest(stream)) | |
); | |
} | |
} | |
} | |
// add two infinite streams | |
function stream_combination(proc, stream_1, stream_2) { | |
if (is_stream_empty(stream_1) || is_stream_empty(stream_2)) { | |
return empty_stream; | |
} else { | |
return stream_pair( | |
proc(stream_first(stream_1), stream_first(stream_2)), | |
function() { | |
return stream_combination( | |
proc, | |
stream_rest(stream_1), | |
stream_rest(stream_2) | |
) | |
} | |
); | |
} | |
} | |
////////////////////////// | |
function fibgen(a, b) { | |
// fibgen was being called before calling stream_pair, wrapping it in function | |
// seems to avoid it. | |
// Below comment is made after the above comment once I understood the reason | |
// It is avoided because the only way to delay immediate evaluation | |
// is to explicitly wrap the call in a zero arg function. | |
// This is the only way to do this without changing the eval | |
// order of function arguments in in Javascript Interpreter. | |
// This will not work. | |
// return stream_pair(a, fibgen(b, (a + b))); | |
// This will work | |
return stream_pair(a, function() {return fibgen(b, (a + b))}); | |
} | |
fibo_Stream = fibgen(0, 1); | |
////////////////////// | |
function int_stream_gen(a) { | |
return stream_pair(a, function() {return int_stream_gen(a)}); | |
} | |
ones = int_stream_gen(1); | |
twos = int_stream_gen(2); | |
threes = stream_combination(function(a,b) {return a + b}, ones, twos); | |
// print first ten elements. | |
stream_map_len( | |
function(x) {console.log(x);}, | |
10, | |
fibo_Stream | |
); | |
/////////////////////////// End of Program //////////////////////// |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment