Currently I have a closure in JS that looks like the following:
var addTo = function(num){
var add = function(inner){
return inner + num;
};
return add;
};
var sum = new addTo(1);
My goal is to use the above closure to compute the sum from 1 all the way to 100 (i.e. sum = 1+2+3+...+99+100). Any help? I know a loop is needed, but am unsure of what should go inside the loop and how to use closure to achieve the goal. Thanks guys.
Currently I have a closure in JS that looks like the following:
All functions create closures, they're only remarkable when advantage is taken of them. ;-)
var addTo = function(num){
I don't know why function expressions are used when declarations are clearer (to me):
function addTo(num) {
then there's:
var add = function(inner){
return inner + num;
}
return add;
}
Which (sticking with an expression) can be:
return function (inner) {return inner + num};
}
Then you call it with new:
var sum = new addTo(1);
which causes addTo to create a new object that is not used, so you might as well do:
var sum = addTo(1);
which produces exactly the same result. So:
function addTo(num) {
return function (inner) {return inner + num};
}
var sum = addTo(1);
document.write(sum(3));
However, this is really just a version of Currying, so that sum will just add the supplied value to whatever was initially supplied to addTo.
If you want to add all the numbers from 0 to some limit, you just need a loop, no closure required:
function sumTo(num) {
var total = 0;
for (var i = 0; i <= num; i++) {
total += i;
}
return total;
}
document.write(sumTo(5)); // 15
Note that supplying a negative number will result in an endless loop, you should protect against that (I'll leave it up to you to work out how).
Try
function sum(x) {
var input = x;
function add(y) {
return input + y;
}
return add;
}
//var sum1 = sum(2);
//console.log(sum1(3)); // 5
console.log(sum(2)(3)); //5
Maybe you want to use recursive instead of loops?
function addTo(initial) {
function add(adder) {
if (initial < 100) {
initial+=1
return add(adder+initial)
}
else {
return adder
}
}
return add(initial)
}
document.write(addTo(1))
As long as the initial values don't go over 100, it would just add with sum of all calculation before + itself + 1.
It looks like the addTo() function returns another function into sum that will add whatever you pass it to the original number (or I assume that's what you meant to write; the first thing to do is change the statement inside of add() to use a += instead of just + to make sure you save the result).
Since you want to add each number from 2 to 100 (since you already passed 1 into addTo()), try writing a for loop that runs from 2 to 100 passing each one into the sum() function to add them all together. Here's an example:
var sum = addTo(1);
for (var i=2; i<100; i++) sum(i);
var result = sum(100);
Here I added 100 after the loop since I wanted to grab the final result. You could also add 100 in the loop and use sum(0) to get the result without changing it after the loop.
Related
function addNumbers(x,y) {
sum = x + y;
var sum;
return sum;
}
addNumbers(5,9);
alert(sum);
It says: Uncaught ReferenceError: sum is not defined
When I put "var sum" before the function it works. What is the reason?
sum is only defined within the function. To use the function's return value, you do that directly:
function addNumbers(x,y) {
var sum;
sum = x + y;
return sum;
}
alert(addNumbers(5,9));
or
function addNumbers(x,y) {
var sum;
sum = x + y;
return sum;
}
var outerSum = addNumbers(5,9);
alert(outerSum);
Also note that I moved the var sum; to the top of the function. It doesn't really matter with var (I wrote a blog post about that), but it's better form. (It does matter with let and const, which you should probably be using instead of var.)
A variable only exists inside of it's scope (rule of thumb: starts at the previous { ends at the matching }), which especially makes sense for functions, as the variables inside the function only exist as long as the function gets executed.
function addNumbers(x,y) { // sum can be used from here on
var sum = x + y; // always declare variables where you ise them first, otherwide you get funny behaviour
return sum; // <-
} // you cannot use sum from here on
Now that means that you cannot access sum outside of addNumbers. However as your function returns the value of sum, you can store that in another variable:
var cool = addNumbers(1, 2);
Now you can use that cool variable and eventually log it.
I think I have a pretty big logic issue here. A function return value isn't recognized by another function. I am not quite sure where the value that is returned by DoStuff goes...why can't I access the value numArray?
It is my understanding that all values inside a function are local to that function...unless I use return, which SHOULD allow me to access that value.
So this code is simply in an external js file...what you see is the only thing in it. My big question is when I return numArray...where does that value go?
function doStuff(){
//document.write("We are testing document writing now!");
let numArray;
let sumArray;
let start = parseInt(prompt("Enter a small number"));
let end = parseInt(prompt("Enter a larger number"));
if (start > end){
alert("Error: first int greater than last!")
} else {
let arraySize = end - start;
numArray = [start];
for (let x = start + 1; x <= end; ++x){
numArray.push(x);
}
console.log(numArray);
return numArray;
}
}
function addArray(numArray) {
console.log(numArray);
}
<form> <input type="button" value="Click Me to generate an array of numbers!" onclick="doStuff()"/> <input type="button" value="Click me to add the array numbers" onclick="addArray()"/> </form>
Console is telling me that numArray is undefined when I try to log it. I am needing to get the array (numArray) and use the data in the array to do some more things to them. Both functions are "called" by onclick buttons on a webpage (so I have to click the DoStuff button before the addArray button).
all values inside a function are local to that function...unless I use
return
Well, this is... partially true. First part is true and there is no "unless". return statement is just pointing to the value that is, well, returned by a function. It doesn't mean that this variable is now global. Value in return is kind of "value of function" and you must store it in a variable if you want to use it later, as you can see in others' answers.
call addArray function from DoStuff function and pass numArray as a parameter to it
function DoStuff() {
let numArray;
let sumArray;
let start = 1;
let end = 5;
if (start > end){
alert("Error: first int greater than last!")
}
else {
let arraySize = end - start;
numArray = [start];
for (let x = start + 1; x <= end; ++x){
numArray.push(x);
}
}
addArray(numArray)
}
function addArray(numArray){
console.log(numArray);
}
In your main js file that contains those onclick functions, you need to have a global variable to store your numArray after you call doStuff function.
Something like this:
let globalNumArray
// on click button doStuff
function (){
globalNumArray = doStuff()
}
// on click button addArray
function() {
addArray(globalNumArray)
}
My big question is when I return numArray...where does that value go?
The return value goes to where you called that particular function.
doStuff() is returning a value, so use the return of this function as a variable. We can assign this returned value to another variable or can use directly within expression. So call dostuff() to get the returned value.
function doStuff(){
//document.write("We are testing document writing now!");
let numArray;
let sumArray;
let start = parseInt(prompt("Enter a small number"));
let end = parseInt(prompt("Enter a larger number"));
if (start > end){
alert("Error: first int greater than last!")
} else {
let arraySize = end - start;
numArray = [start];
for (let x = start + 1; x <= end; ++x){
numArray.push(x);
}
console.log(numArray);
return numArray;
}
}
console.log('HERE IS ARRAY: '+doStuff());
Edit:
The reason why global variables are discouraged in js is, because all code has a single global namespace, where javascript has implied global variables automatically (like variables which are not explicitly declared in local scope are automatically added to global namespace). Relying too much on global variables can result in some collisions between scripts on the same page. This doesn't mean, that you mustn't use global variables but you shouln't use them light-mindedly. If you need a variable to be accessable after the function has finished, your choices are limited, so either use a global variable or pass the variable to the function you need it in.
You just need to save the result of doStuff and then access that variable in addArray:
var result
function doStuff() {
//document.write("We are testing document writing now!");
let numArray;
let sumArray;
let start = parseInt(prompt("Enter a small number"));
let end = parseInt(prompt("Enter a larger number"));
if (start > end) {
alert("Error: first int greater than last!")
} else {
let arraySize = end - start;
numArray = [start];
for (let x = start + 1; x <= end; ++x) {
numArray.push(x);
}
result = numArray; // save result for later (has to be a global scope)
}
}
function addArray() { // you defined this without an input in your form, so stick to that
if (result) // check if value exists
console.log(result);
else
console.log("Please enter the numbers boundaries first first.");
}
<form>
<input type="button" value="Click Me to generate an array of numbers!" onclick="doStuff()" />
<input type="button" value="Click me to add the array numbers" onclick="addArray()" />
</form>
Here's a couple things I think could help you out:
1) Split your code. doStuff, prompts the user for input, but it also generates an array containing values from min-max. You should have a separate function that generates an array from min to max. Splitting it up will make it easier to identify a problem.
2) A few solutions suggest a global variable this can be dangerous. When
you must share state limit its scope to only what needs to access that state.
3) Make your interfaces consistent. You should not return a value one instance and nothing in another. If there is an error make sure you are consistent with how you notify the caller.
function buildArray(start, end) {
let arr = [];
if (start > end) {
// There are a lot ways to deal with this
// But you want a consistent interface for letting
// the caller no that start < end
throw {
message: 'Start can\'t be bigger than end',
};
}
for (let x = start; x <= end; x++) {
arr.push(x);
}
return arr;
}
// encapsulate the variable numArray, so that it is only accessible
// to the methods that need it
var numArrayModule = (function(){
let numArray = [];
return {
doStuff: function(){
let start = parseInt(prompt("Enter a small number"));
let end = parseInt(prompt("Enter a larger number"));
try {
numArray = buildArray(start, end);
} catch(err) {
console.log(err);
}
},
addArray: function(){
console.log(numArray);
},
}
}());
// You may use these as onClick handlers as well.
numArrayModule.doStuff();
numArrayModule.addArray();
I'm looking to write a function in Javascript that will take no arguments, but produce a different (predictable) output each time. I'll be using it for testing, so I need to be sure that I can predict the outputs, meaning that using Date.now() will not work. I'm thinking about using a seeded RNG (or PRNG), but I'm wondering if there are any alternate solutions.
Edit: the function must be self contained, no variables or data outside the scope of the function.
Just modify a variable in a wider scope.
var my_counter = 0;
function count() {
return ++my_counter;
}
console.log(count());
console.log(count());
console.log(count());
console.log(count());
console.log(count());
console.log(count());
I would go with a randomly seeded number solution that maps to whatever results you wish to return. That way you can keep it contained within the function.
OR have an array of results that can be returned and simply increment an index (with a modulus so that the index wraps back to the start again) and return the result at the indexed value. Something like...
var index = 0;
var results = [ "x", "y", "z" ];
function test() {
var value = results[index];
index = (index++) % results.length;
return value;
}
So, the function will keep looping through the x, y and z results. You can set as many predictable results as you wish.
Since via closure any function can hold state (say, your counter), you could generate any arbitrary-but-fixed data array (like, a string with the digits of Pi) and return always the next value:
var getArbitraryValue = (function () {
var i = 0;
var arbitraryValue = Math.PI.toString();
return function () {
// you may want to reset the index here, once your string runs out
return arbitraryValue.charAt(i++);
}
} ());
Repeating calls to getArbitraryValue will return the digits of Pi.
This is a fun use case for ES2015 generators and iterators, if you don't mind involving babel:
function* mygenerator() {
let i = 0;
while(true){
yield i++
}
}
const generator = mygenerator();
const noArgsDifferentResult = () => generator.next().value;
console.log(noArgsDifferentResult()); // 0
console.log(noArgsDifferentResult()); // 1
console.log(noArgsDifferentResult()); // 2
Try it out in the Babel live parser https://babeljs.io/repl/
I have been reading through Chapter 5 last night and throughout the morning and can't seem to get the higher order functions concepts to stick. Here are the examples:
//I understand this first function, I am including it because it is used in the next function.
function forEach(array, action) {
for (vari = 0; i < array.length; i++)
action(array[i]);
}
forEach(["Wampeter", "Foma", "Granfalloon"], print);
function sum(numbers) {
var total = 0;
forEach(numbers, function(number) {
total += number;
});
return total;
}
To my understanding the function sum is taking the argument numbers, which I believe comes in as an array? Now, when the forEach function is called (within sum), it takes the array numbers passed to sum and then it also takes an anonymous function?
I am really confused on what this anonymous function is actually doing. It is taking the parameter number but what else is it doing? Does this anonymous function imply that in that parameter, a function like print or show will be passed the parameter number? In other words it would look something like this
function([10,12,11]) {
var total = 0
forEach([10,12,11]), show(???)
//at this point it would iterate over the array, and use the action passed to display `//the pointer in the array. What I think is happening is that it is taking this pointer value and adding it to the total.` //
I have been trying to wrap my head around this example for a while, if anyone knows of a good explanation or any other documentation to read over I would greatly appreciate it, thanks!
The anonymous function is applied to every currently selected element. You can see better how this works if you unroll (execute stepwise) the loop (pseudocode, * means current element):
var total = 0;
forEach([*1, 2, 3]), fun(1)) => total = 0 + 1 = 1
forEach([1, *2, 3]), fun(2)) => total = 1 + 2 = 3
forEach([1, 2, *3]), fun(3)) => total = 3 + 3 = 6
You can rewrite the sum function like this:
// because there is no "pass by reference" in JavaScript for
// "simple" types, total must be wrapped in an object
// in order to return the sum through the parameter for the showcase
var result = { total: 0 }
function sum(numbers_array) {
for (var i = 0; i < numbers_array.length; i++) {
accumulate(result, numbers_array[i]);
}
}
function accumulate(acc, number) {
acc.total += number;
}
In this case the accumulate function does the same as the anonymous function. When the accumulate function is declared within the scope of the sum function, then the total variable is like global (it is known) to the accumulate function and then there is no need of the first parameter, so the function becomes like the one you already know:
var total = 0;
function sum(numbers_array) {
function accumulate(number) {
total += number;
}
for (var i = 0; i < numbers_array.length; i++) {
accumulate(numbers_array[i]);
}
}
Next step would be to extract and pass the accumulate function as parameter:
var total = 0;
function accumulate(number) {
total += number;
}
// notice, that JavaScript knows how many parameters your function expects
function sum(numbers_array, action) {
for (var i = 0; i < numbers_array.length; i++) {
action(numbers_array[i]);
}
}
What left is to extract the iteration and the code will look like this one in the book.
Let me see if I can explain this easily for you:
The forEach() function accepts two parameters, the first one called array is obviously an array or an array-like object, the second parameter called action is actually a function.
forEach() visits each element in the array passed to it and applies to each element in the array the function passed to it as the second parameter.
So forEach() calls the function passed to it named action for each element in the array and it gives the function the array element as a parameter.
The function sum(numbers) accepts an array as you have though, and it uses forEach() inside itself to calculate the sum of numbers in that array using the anonymous function.
Remeber that the anonymous function is called once for each element in the array passed to sum() so it actually sums the elements in the array.
In simple words : to make your code more generic and concise.
Ex:
Lets say we want to find the max element in an Array :
That's pretty easy and cool :
In java script we will write :
var array = [10,20,30,40,50,60]
function maxEle(array){
var max = array[0];
for(var i=0;i< array.length;i++){
if(max < array[i]){
max = array[i];
}
}
console.log(max);
}
So this will give me the maximum element in an array.
Now after few days, some one asked me that your max is working pretty cool, I want a function which will print the minimum in an array.
Again I will redo the same thing, which i was doing in finding Max.
function minEle(array){
var min = array[0];
for(var i=0;i< array.length;i++){
if(min > array[i]){
min = array[i];
}
}
console.log(min);
}
Now this is also working pretty cool.
After sometime, another requirement comes up : I want a function which will print the sum of all the elements of the array.
Again the code will be similar to what we have written till now, except now it will perform summation.
function sumArr(array){
var sum = 0;
for(var i=0;i< array.length;i++){
sum = sum + array[i];
}
}
console.log(sum);
}
Observation :
After writing these bunch of codes, I m rewriting almost the same thing in every function, iterating over the Array and then performing some action.
Now writing the repetitive code is not a cool stuff.
Therefore we will try to encapsulate the varying part i.e action viz min, max, summation.
Since its feasible to pass functions as arguments to a function in FPL.
therefore we will re-factor our previously written code and now write a more generic function.
var taskOnArr = function(array, task){
for(var i=0;i<array.length;i++){
task(array[i]);
}
}
Now this will be our generic function, which can perform task on each element of Array.
Now our tasks will be :
var maxEle = array[0];
var taskMaxEle = function(ele){
if(maxEle < ele){
maxEle = ele;
}
}
Similarly for min element :
var minEle = array[0];
var taskMinEle = function(ele){
if(minEle > ele){
minEle = ele;
}
}
Also for summation of Array :
var sum = 0;
var taskSumArr = function(ele){
sum = sum + ele;
}
Now we need to pass functions to taskOnArr function :
taskOnArr(array,taskSumArr);
console.log(sum);
taskOnArr(array,taskMinEle);
console.log(minEle);
taskOnArr(array,taskMaxEle);
console.log(maxEle);
My professor has given us the following snippet of Javascript which we are supposed to analyze:
function createMultiplyer(multiple) {
n = multiple;
return function(num) {
return num * n;
};
}
var fiveMultiplyer = createMultiplyer(15);
var x = fiveMultiplyer(10);
alert(x);
alert(fiveMultiplyer);
This piece of code outputs an alert containing the text "150" followed by another alert which reads function(num) { return num * n; }. However, I cannot seem to understand why that is the case.
Can someone help me trace through the code and explain what is happening?
1 Let's consider line
var fiveMultiplyer = createMultiplyer(15);
After it, fiveMultiplyer variable will have return value of createMultiplyer function (that's how functions work). And that return value is
function(num) {
return num * n;
};
So, the code is similar to this (about n later)
var fiveMultiplyer = function(num) {
return num * n;
};
2 The next line is
var x = fiveMultiplyer(10);
Here we just invoke the function above. It also uses variable n: that variable is set in createMultiplyer function: n = multiple;. Thus, in our case n is 15 and fiveMultiplyer(10) is equivalent to 10 * 15.
That's all. Hope it helps.
edit
I'll also note that n is a global variable the way it's declared. So, you can access it from anywhere in the code.
var fiveMultiplyer = createMultiplyer(15); // Create a function that multiplies with 15
This function is locally known as fiveMultiplier
var x = fiveMultiplyer(10); // Invoke the multiply-by-15 with argument 10
The result is locally known as x
alert(x); // 150
alert(fiveMultiplyer); // The definition of multiply-by-15 as
// it is returned from createMultiplyer
function createMultiplyer(multiple) { // Returns a new function which
// multiplies with "multiple"
[var] n = multiple; // Note: "var" should have been used to keep "n"
// in scope (within "createMultiplyer").
return function(num) { // Return definition of multiplier function
return num * n; // "num" = arg. when invoked, "n" = multiplier at
// define time (when "createMultiplyer" was called)
};
}
The best way to think of it is as a class or object. var fiveMultiplyer is creating an object that holds a value n = 15 and has a function that accepts a number and multiplies it by n.
In Java this would look something like this
public class Multiplyer {
private int n;
public Multiplyer(int n) {
this->n = n;
}
public int multiple (int m) {
return n*m;
}
}
Multiplyer myMultiplyer = new Multiplyer(15);
System.out.println( myMultiplyer.multiple(10) );
In the JavaScript however the variable fiveMultiplye does not have to call its method, you simple pass it the required variables and it calls the method and returns for you.
Hope that helps.
In JavaScript, you can have a variable which acts as a function too.
var fiveMultiplyer = createMultiplyer(15);
You are calling a CreateMultiplyer(15) function.
This function returns you another function and that is associated
with the fiveMultiplyer var.
var x = fiveMultiplyer(10);
You are actually invoking the function which was returned in previous step.
hence evaluating the value to 10 * 15 = 150
alert(x);
As explained this returns 150
alert(fiveMultiplyer);
As explained this returns the complete function
returned by createMultiplyer().