Skip to content

Instantly share code, notes, and snippets.

@ankithooda
Last active June 24, 2024 13:20
Show Gist options
  • Save ankithooda/6313a460679b080c0f045a68180a53db to your computer and use it in GitHub Desktop.
Save ankithooda/6313a460679b080c0f045a68180a53db to your computer and use it in GitHub Desktop.
Infinite Stream Objects in Javascript
//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