Emulate/use Continuations in JavaScript? - javascript

I have a function that computes product of numbers in an array. The function should work like this
function prod (array){
//compute and return product
}
var arr = [1,2,3,0,4,5,0,6,7,8,0,9];
the function call:
prod(arr); //should return 6
prod(arr); //should return 20
prod(arr); //should return 336 (6*7*8)
prod(arr); //should return 9
prod(arr); //should return 0
prod(arr); //should return 0
prod(arr); //should return 0
In scheme, this is done with continuations, by storing previous state of the function (state of the function is captured just before its exit point) see this
So, in short, I want the javascript function return different values at different times with same parameter passed everytime.
JavaScript is a well designed language, so I hope there must be something which can emulate this. If there happens to be nothing in JS to do it, I do not mind to conclude with failure and move on. So, feel free to say its impossible.
Thanks.

JavaScript is not capable of supporting continuations: it lacks tail-calls.
Generally I would write this to use a "queue" of sorts, although CPS is also do-able (just have a finite stack :-) Note that other state can also be captured in the closure, making it an "explicit continuation" of sorts ... in a very gross sense.
Example using a closure and a queue:
function prodFactory (array){
// dupe array first if needed, is mutated below.
// function parameters are always locally scoped.
array.unshift(undefined) // so array.shift can be at start
// also, perhaps more closured state
var otherState
// just return the real function, yippee!
return function prod () {
array.shift()
// do stuff ... e.g. loop array.shift() and multiply
// set otherState ... eat an apple or a cookie
return stuff
}
}
var prod = prodFactory([1,2,3,0,4,5,0,6,7,8,0,9])
// array at "do stuff", at least until "do stuff" does more stuff
prod() // [1,2,3,0,4,5,0,6,7,8,0,9]
prod() // [2,3,0,4,5,0,6,7,8,0,9]
prod() // [3,0,4,5,0,6,7,8,0,9]
Happy coding.
"Finished implementation". Although this particular problem can avoid array mutation and just use an index: the same concepts apply. (Well, slightly different. With just an index the closed over variable would be altered, whereas with this approach an object is mutated.)
function prodFactory (array) {
array = array.slice(0)
return function prod () {
var p = 1
for (var n = array.shift(); n; n = array.shift()) {
p *= n
}
return p
}
}
var prod = prodFactory([1,2,3,0,4,5,0,6,7,8,0,9])
prod() // 6
prod() // 20
prod() // 336

You can give the function a property that will be remembered between calls:
function prod (array){
if (typeof prod.index === "undefined" || prod.currentArray != array) {
prod.currentArray = array;
prod.index = 0;
}
if (prod.index >= array.length)
return 0;
//compute and return product
var p = 1,
c;
while (prod.index < array.length) {
c = array[prod.index++];
if (c === 0)
return p;
p *= c;
}
return p;
}
I'm just guessing from your description of what should be returned that on an individual call to the function it should take the product of all of the numbers up to but not including the next zero or the end of the array. Calls after the end of the array should return 0? I may have the algorithm wrong for that, but you get the idea for what I'm suggesting to remember the function state between calls.
I've added a property to remember the current array being processed. As long as you keep passing the same array in to the function it will continue with the next elements, but if you pass a different array it will reset...

you can try something like
var index = 0;
function prod (array){
if(index < array.length){
var prod=1;
for(int i=index;i<array.length;i++){
if(array[i] != 0){
prod = prod * array[i];
}
else{
index = i+1;
return prod;
}
}
}
return 0;
}
this will update the global variable index everytime the function is called.

What you're looking for here are generators. As of 1.7, JavaScript supports them.

Related

Converting JavaScript function to C++

I was working on a Dynamic Programming Problem and was able to code up a Javascript solution:
function howSum(targetSum,numbers,memo = {}){
//if the targetSum key already in hashmap,return its value
if(targetSum in memo) return memo[targetSum];
if(targetSum == 0) return [];
if(targetSum < 0) return null;
for(let num of numbers){
let aWay = howSum(targetSum-num,numbers,memo);
if(aWay !== null){
memo[targetSum] = [...aWay,num];
return memo[targetSum];
}
}
//no way to generate the targetSum using any elements of input array
memo[targetSum] = null;
return null;
}
Now I was thinking over how I could translate this into a CPP code.
I would have to use a reference to an unordered map for the memo object.
But how should I go about returning the empty array and null values as in the base condition?Should I return an array pointer and realloc it when inserting an element?Wouldnt that be a C way of programming it?
Also how should I go about passing the default parameter to the memo unordered map in C++?Currently I have overloaded the function which creates the memo unorderd map and passes its reference.
Any guidance will be appreciated as I can solve future questions.
I was stuck in this problem too. This is how I made it work.
// howSum function
vector<int> howSum(int target, vector<int> numbers, unordered_map<int, vector<int>> &dp ){
// base case 1 - for dp
if(dp.find(target)!=dp.end()) return dp[target];
// making a vector to return in the following base cases
vector<int> res;
// base case 2
if(target == 0) {
return res;
}
// base case 3
if(target<0) {
res.push_back(-1); // using -1 instead of NULL
return res;
}
// the actual logic for the question
for(int i=0;i<numbers.size();i++){
int remainder = target - numbers[i];
vector<int> result = howSum(remainder,numbers,dp); // recursion
// if result vector doesn't contain -1, push target to result vector
if(find(result.begin(),result.end(),-1)==result.end()){
result.push_back(numbers[i]);
dp.emplace(target,result);
return result;
}
}
res.push_back(-1);
dp.emplace(target,res);
return res;
}
// main function
int main(){
vector<int>numbers = {20,50};
unordered_map<int, vector<int>> dp;
vector<int> res = howSum(300,numbers,dp);
for(int i=0;i<res.size();i++){
cout<<res[i]<<" ";
}
cout<<endl;
}
Here is my take at it:
#include <optional>
#include <vector>
#include <unordered_map>
using Nums = std::vector<int>;
using OptNums = std::optional<Nums>;
namespace detail {
using Memo = std::unordered_map<int, OptNum>>;
OptNums const & howSum(int targetSum, Nums const & numbers, Memo & memo) {
if (auto iter = memo.find(targetSum); iter != memo.end()) {
return iter->second; // elements are std::pair<int, OptNums>
}
auto & cached = memo[targetSum]; // create an empty optional in the map
if (targetSum == 0) {
cached.emplace(); // create an empty Nums in the optional
}
else if (targetSum > 0) {
for (int num : numbers) {
if (auto const & aWay = howSum(targetSum-num, numbers, memo)) {
cached = aWay; // copy vector into optional
cached->push_back(num);
}
}
}
return cached;
}
} // detail
std::optional<Nums> howSum(int targetSum, Nums const & numbers) {
detail::Memo memo;
return detail::howSum(targetSum, numbers, memo);
}
Some comments:
using two functions, one that creates the memo and passes it into the real implementation function is a good pattern. It makes the user-facing interface clean.
the "detail" namespace is just a name, no magic meaning, but is often used to indicate implementation detail.
In the implementation, I return references to an optional. This is an optimization to avoid copying the return vectors in every call where the algorithm unwinds from the recursion. This does require some care, however, because you must be careful to return references to objects that will outlive the local scope (so no returning std::nullopt, or the reference binds to a temporary optional, for example.) That is also why I always create the element in the memo object--even in the negative case--so I can return a reference to it safely. Note, operator[] applied to an unordered_map will create the element if it does not exist, while find will not.
Since the reference returned by the detail function has a lifetime only as long as the memo declared in the caller, the caller itself must return a copy of the optional it gets back, to ensure that the data is not destroyed during the cleanup of the function call. Note, it does not return a reference.
Also, the "if" inside the for loop has a little bit going on. It declares a local reference, initializes it to the result of the recursive call. That whole expression is a reference to optional, which has an implicit conversion to bool that is true if the optional holds a value. This is a useful idiom worth pointing out, though to be more explicit this is equivalent:
if (auto const & aWay = howSum(targetSum-num, numbers, memo); aWay.has_value())
Here's a fleshed out example, with a few test cases to show it work.
https://godbolt.org/z/cWrdhvM1n

Is there any point in creating a custom iterator for an array in node.js?

I need to parse an 80GB+ CSV file, and thought this a good opportunity to understand iterators in JavaScript (and then probably use an existing library such as csv-iterator, fast-csv, etc).
Looking at an iterator example on MDN HERE, I see this code:
function makeIterator(array) {
var nextIndex = 0;
return {
next: function() {
return nextIndex < array.length ?
{value: array[nextIndex++], done: false} :
{done: true};
}
};
}
Which is pretty self-explanatory. I can create an iterator for an array:
var iteratorForMyArray = makeIterator([1,2,3,4,5,6,7,8,9, etc])
And then I can use my shiny new iterator to 'iteratively' pull out values of my array:
var val0 = iteratorForMyArray.next().value
var val1 = iteratorForMyArray.next().value
etc
I can see why this is useful when parsing a CSV file. I'm wondering if there is any point in creating such an iterator for a simple array?
I often find that while simplified examples are useful for understanding, it's sometimes hard to see when the example is only useful as an example vs is actually useful in programming.
Because JavaScript already provides 2 mechanisms for creating iterators over array structures:
1: Basic for loop
for (let i = 0, i < [1,2,3,4,etc]; i++) {
...
}
2: Array.prototype.forEach
[1,2,3,4,etc].forEach(function(val, i, arr) {
...
})
(which I have just seen is slow on this site)
Questions:
Does my custom iterator offer anything that these iterators don't?
Do both these 'in-house' iterators create 'iterators' (i.e. what I understand as sequential pointers to values in data structures)? Or am I off by miles...
ForEach guarantees order, as well as it'll skip invalid indexes etc. Your iterator doesn't provide anything extra when compared to a standard for loop, it'll just be slower, as you're calling a function to get the next item, where a basic for loop doesn't have this overhead. Use a for loop and cache the length to start for better performance.
One good feature of iterators is that each call gets the next element, whereas forEach it's all or nothing (you can't exit early), and with both a for loop and forEach all the logic must be inside the loop.
Consider an array iterator like:
function arrayIterator(array) {
// Get array indexes as an array
var indexes = Object.keys(array)
.filter(
// Test for valid Array index property
key => key == +key && key >= 0 && key.length == String(+key).length)
// Sort as numbers
.sort(function(a, b){return a-b});
// Parameters held in closure
var current = 0;
var count = 0;
var maxCount = indexes.length;
// Return iterator function
return function() {
return ++count > maxCount? 'done' : array[indexes[current++]];
};
}
var arr = [0,1,,,4,5,6];
// Add non-index numeric property
arr['01'] = '01';
// Add indexable numeric property
arr['10'] = '10';
// Add some other property
arr.foo = 'foo';
var x = arrayIterator(arr);
console.log(x()); // 0
console.log(x()); // 1
console.log(x()); // 4
console.log(x()); // 5
console.log(x()); // 6
console.log(x()); // 10
console.log(x()); // 'done'
console.log(x()); // 'done'
I'm sure there's more to be done in regard to checking valid indexes and also testing that an index still exists when the iterator is called, but is shows the concept.
There also needs to be some documentation about what happens when the array is modified between calls.

Null value in array-flattening recursion using `for` vs `slice`: why are the returns of these two functions different?

Below I have provided two code snippets which, in my mind, ought to do the same thing. In the first snippet I get a "null" value. I imagine this is because a null value is passed into the function as arr when I call steamrollArray(arr[0]) on [], pushing the null value into the accumulator.
What I don't know, and I'm hoping I can have some help with, is what might be an elegant way to avoid this particular issue?
I'd like both functions to give the same output when given the same input.
As an ancillary point: I would be interested to know if anyone could point me to a method of bench-marking these two methods against one another - this is something I know nothing about, beyond the fact that it's "a thing," and it would be helpful for me generally to understand how to do such a thing, and specifically how one might do so with this problem.
As another ancillary point: is there a interactive javascript interpreter, in the same way that you can get an interactive python interpreter (where you can play with / test things in the command line)?
Version 1: "natural" recursion - returns [1,null,2,3]
function steamrollArray(arr) {
// I'm a steamroller, baby
//recursive (is an array)
var accum = [];
if (Array.isArray(arr)) {
accum = accum.concat(steamrollArray(arr[0]));
if (arr.length > 1) {
accum = accum.concat(steamrollArray(arr.slice(1)));
}
} else {
accum.push(arr);
}
return accum;
}
console.log(
steamrollArray([1, [], [3, [[4]]]])
);
Version 2: for loop recursion - returns [1,2,3]
function steamrollArray(arr) {
// I'm a steamroller, baby
//recursive (is an array)
var accum = [];
for (var i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
accum = accum.concat(steamrollArray(arr[i]));
} else {
accum.push(arr[i]);
}
}
return accum;
}
console.log(
steamrollArray([1, [], [3, [[4]]]])
);
In version 1 you are pushing arr[0] without checking if there is an element inside arr[0]. So at the second call to steamrollArray where you are passing an empty array [], arr[0] will be undefined:
var arr = [];
console.log(arr[0]);
Why this isn't happening in version 2? It's because you have a for loop wrapping the push calls (for(var i = 0; i < arr.length...). So when the empty array is passed, the for loop is never entered. because 0 < 0 is false.
You can fix version 1 by wrapping the push call inside an if statement like this: (the push will happen when steamrollArray get called with the argument arr[0])
if(arr.length) // if length is not 0
accum = accum.concat(steamrollArray(arr[0]));
Ancillary 2: NodeJs is a great javascript runtime. It comes with a command line interface. Try it!

Can forEach in JavaScript make a return? [duplicate]

This question already has answers here:
What does `return` keyword mean inside `forEach` function? [duplicate]
(2 answers)
Why does this forEach return undefined when using a return statement
(5 answers)
Closed 1 year ago.
I wonder if forEach in JavaScript can make a return, here is my code:
var a = [0, 1, 2, 3, 4];
function fn(array) {
array.forEach(function(item) {
if (item === 2) return false;
});
return true;
}
var ans = fn(a);
console.log(ans); // true
I want to find out if 2 is in my array, if so, return false, but it seems that the forEach function has looped the whole array and ignore return.
I wonder if I can get the answer I want with forEach ( I know I can get what I want using for(..))? dear friend, pls help me, with great thanks!
You can use indexOf instead https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf
function fn(array) {
return (array.indexOf(2) === -1);
}
Also from the documentation for forEach - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
Note: There is no way to stop or break a forEach() loop other than by
throwing an exception. If you need such behaviour, the .forEach()
method is the wrong tool, use a plain loop instead.
So, the return value cannot be used the way you are using it. However you could do a throw (which is not recommended unless you actually need an error to be raised there)
function fn(array) {
try {
array.forEach(function(item) {
if (item === 2) throw "2 found";
});
}
catch (e) {
return false;
}
return true;
}
In this case .indexOf() is probably what you want, but there's also .some() when a simple equality comparison is too simple:
var ans = a.some(function(value) { return value === 2; });
The .some() function returns true if the callback returns true for any element. (The function returns as soon as the callback does return true, so it doesn't bother looking beyond the first match.)
You can usually use the .reduce() function as a more general iteration mechanism. If you wanted to count how many instances of 2 were in your array for example:
var twos = a.reduce(function(c, v) { if (v === 2) c += 1; return c; }, 0);
Others have mentioned .indexOf() and .some(). I thought I would add that a good old fashioned for loop gives you the absolute most iteration control because you control the iteration and your processing code is not embedded in a callback function.
While .indexOf() already does exactly what you need, this code just shows how you can directly return when using the old fashioned for loop. It is somehow out of favor these days, but is often still the best choice for better looping control.
function fn(array) {
for (var i = 0, len = array.length; i < len; i++) {
if (array[i] === 2) return false;
}
return true;
}
Using the for loop, you can iterate backwards (useful when removing items from the array during the iteration), you can insert items and correct the iteration index, you can immediately return, you can skip indexes, etc...
forEach returns undefined by specification. If you want to find out if a particular value is in an array, there is indexOf. For more complex problems, there is some, which allows a function to test the values and returns true the first time the function returns true, or false otherwise:
a.some(function(value){return value == 2})
Obviously a trivial case, but consider if you want to determine if the array contains any even numbers:
a.some(function(value){return !(value % 2)})
or as an ECMA2015 arrow function:
a.some(value => !(value % 2));
If you want to test if a particular value is repeated in an array, you can use lastIndexOf:
if (a.indexOf(value) != a.lastIndexOf(value) {
// value is repeated
}
or to test for any duplicates, again some or every will do the job:
var hasDupes = a.some(function(value, i, a) {
return a.lastIndexOf(value) != i;
});
An advantage of some and every is that they only process members of the array until the condition is met, then they exit whereas forEach will process all members regardless.
You said you want with forEach, so I modified your code:
function fn(array) {
var b = true;
array.forEach(function (item) {
if (item === 2) {
b = false;
}
});
return b;
}
var a = [0, 1, 2, 3, 4];
function fn(array, callback) {
var r = true;
array.forEach(function(item) {
if (item === 2) r = false;
});
callback(r);
}
fn(a, function(data) {
console.log(data) //prints false.
});
You can use callbacks as mentioned above to return the data you need. This is not same as the return statement but you will get the data.

Javascript while loop with function as conditional

My understanding is that the contents of a while loop executes while the condition is true. While working off of an example from an awesome O'Riely book, I've come across this implementation of the while loop...
window.onload = function(){
var next, previous, rewind; // globals
(function(){
// Set private variables
var index = -1;
var data = ['eeny', 'meeny', 'miney', 'moe'];
var count = data.length;
next = function(){
if (index < count) {
index ++;
};
return data[index];
};
previous = function(){
if (index <= count){
index --;
}
return data[index];
};
rewind = function(){
index = -1;
};
})();
// console.log results of while loop calling next()...
var a;
rewind();
while(a = next()){
// do something here
console.log(a);
}
}
I guess I'm wondering why, in this code, the while loop is not resolving to true infinitely? The function, next() isn't returning false after var index stops incrementing (++), is it? Shouldn't the console just be outputting eeny, meeny, miney, moe, moe, moe, moe.....etc...
I know this has probably been asked in some form, but have done searching and can't find a question or answer that explains using while (a = function()) {// do something} and how this loop is stopping after one pass through the array.
About why while (a = next()) {/*do something*/} doesn't repeat infinitely, it's about being coerced to false that counts - arguments are converted to booleans before being tested by the while loop. Things that coerce to false include 0, -0, undefined, null, "", NaN, and of course false itself.
When you assign something, it returns the value of the assignment itself. For example, if you do something like this:
var a;
console.log(a = '1234567890abcdefghijklmnopqrstuvwxyz');
It will log 1234567890abcdefghijklmnopqrstuvwxyz.
When the next performs index++, this increments the counter for the element index in the data array. This means that it will look for the next element in the data array every time you run the next() function - if there are no more elements, it will return undefined and therefore end the loop.
For example, see this:
var index = 0;
data = ['a','b','c'];
data[index]; // 'a'
index++;
data[index]; // 'b'
index++;
data[index]; // 'c'
index++;
data[index]; // undefined - if passed this will coerce to false and end the loop
Boolean(data[index]); // false
if (index < count) {
index ++;
};
When index is count - 1, this will still change index to count, right? And count is data.length. So, it then does this:
return data[index];
Which becomes
return data[data.length];
Since the length of an array is out of bounds of the array (they are zero-based), it will give undefined.
while(a = next()){
will become
while(a = undefined){
Since undefined is a falsy value, the loop will not be entered.
No,
It is not going to be an infinite loop. The while loop is basically going through the array and outputting it and when it is at the end of the array it just returns false and quits the loop.
This is something like;
foreach(a as nextArray)
{
//output
}
Hope this helps.

Categories

Resources