Currying function does not update - javascript

I am trying to write a currying function in JavaScript,the inner function does not update the value of the array args:
var myCurry=function(fn)
{
var len=fn.length;
var _slice=Array.prototype.slice;
var args=_slice.call(arguments,1);
console.log(args.length);
return function next()
{
var rem=_slice.call(arguments,0)
args.concat(rem);
console.log(args.length);
if(len<=args.length)
return fn.apply(null,args);
else
return next;
}
}
I call it like this:
var _sum=myCurry(sum,2);
var res=_sum(2);
var res2=res(3,4);
console.log(res2);
This returns the function next at all times,presumably because the array is not updated.How do I fix this error to ensure that the function work?

It's because .concat() doesn't mutate the array. Use .push() instead if you want to mutate the original.
args.push.apply(args, rem);
Or if you didn't care if the original was replaced, just assign the return value from .concat()
args = args.concat(rem);

Oops:
args.concat(rem);
Instead:
args = args.concat(rem);
concat() performs no in-place modifications. It returns a new Array

Related

return function returns array values using Closure

I'm trying to use Closure in JS in order to declare a function named **expandArray()** which contain an Array named **myArray**and Returns an anonymous function that directly modifies myArray by increase the values by 1 than the returned function then returns the value of **myArray**. My Problem here one the last part where the returned function return a function not Array value ?!
This is my code
function expandArray() {
const myArray = [1, 1, 1];
return function () {
myArray.forEach( function (num, index, myArray) {
myArray[index] = num + 1;
});
return myArray;
};
}
console.log(expandArray());
As its closure, you have invoked it only once like expandArray() , which return the function itself, which is below
ƒ () {
myArray.map( function (num, index, myArray) {
myArray[index] = num + 1;
});
return myArray;
}
you need to invoke it again to get your result back as below
expandArray()() //[2, 2, 2]
Ref: How do JavaScript closures work?
You've written a function that returns a function when you run it:
function expandArray() {
const myArray = [...];
// return this when we run expandArray():
return function() {
...
}
}
So if you run expandArray(), it is going to return your anonymous function. Exactly as you wrote it to do.
If you then want to get an actual reference to that internal myArray, you'll now need to actually run that returned function, so:
var getMyArray = expandArray();
var result = getMyArray();
console.log(result);
Just fyi, you are doing something very similar to the memoization pattern.
To address your problem: as everyone else has already said, you return a function from expandArray. What you want is to return the closed array (after incrementing every element).
To do this, you can use something called immediately-invoked function expression in combination with arrow functions to simplify your code:
const expandArray = (() => {
const myArray = [1, 1, 1];
return () => {
myArray.forEach((num, index) => {
myArray[index] = num + 1;
});
return myArray;
};
})();
console.log(expandArray());
console.log(expandArray());
console.log(expandArray());
There are a couple of things incorrect with your code.
you can't change the values of variables declared within const. In the case of Objects and Arrays, you aren't allowed to assign a new reference with a new Array or Object. We change the declarative operator to let instead of const.
myArray.map doesn't mutate myArray, it returns a new array based on the input from myArray and your passed in function that adds 1 to each value. We can fix this by assigning myArray.map to the already declared myArray. That is to say, we're overwriting the old Array with a new one. This is why const in the above bullet point won't work.
Your map function parameters are unnecessary The parameters for it that are most often used are the first two available, which is the item in the array and the index of that item. Since we're iterating over each number using map the function can simply return the item (declared as num in your code) plus 1. This will return a new array with your changed values. So we don't need the index at all..
When you return a function from a function you need to invoke both to get the second return value. When using a closure you need to keep a reference to the initial returned function. This is confusing but if you think of it as levels - in your expandArray function you have two levels. The function itself and the function you're returning. when you call expandArray() you're invoking the first level, and making the second level available to be invoked, this is why expandArray() returns the second function and expandArray()() will return the value from the second function. We save the returned function in a variable called add_to_array by setting it equal to expandArray(), and then we consistently invoke add_to_array to return the new Array with the changed values.
This is the most confusing part of closures, but what is happening is that the add_to_array variable is like a wedge in the function. It stops myArray from being deleted by the Browser because it requires the function to exist in the event that it needs to be invoked again. It's kind of like a bookmark in a book. For the story to make sense whenever you open it, you don't just tear out the pages before the bookmark. You keep the story intact because in five years when you come back to it you may need to read the previous pages at the bookmark to remember where you were. A closure works the same way. It can't remove the variables from the initial expandArray function call because add_to_array is a placeholder in the middle of it. The reference point keeps the book open.
(for more info on closures you can check out this article here Destroying Buildings - A Guide to JavaScript Closures)
function expandArray() {
let myArray = [1, 1, 1];
return function () {
myArray = myArray.map( function (num) {
return num + 1;
});
return myArray;
};
}
let add_to_array = expandArray();
console.log( add_to_array(),add_to_array(),add_to_array() );
In your original code, you're only getting the return value of expandArray(), which is the function you're trying to use as a closure. In order to get the closure's return value, try this out:
function expandArray() {
const myArray = [1, 1, 1];
return function () {
myArray.forEach( function (num, index, myArray) {
myArray[index] = num + 1;
});
return myArray;
};
}
console.log(expandArray()());
The second set of parentheses after the call to expandArray() will invoke the closure and return the values you're seeking.
Old post, but I still like to contribute. I came up with this solution, as I think you want add something to the array instead of incrementing the numbers.
function expandArray() {
let myArray = [1, 1, 1];
return function() {
myArray.push(1)
return myArray
}
}
const array = expandArray();
const result = array();
console.log(result)
3years after this question was posted this lines of code works fine for me
function expandArray() {
let myArray = [1, 1, 1];
return function() {
myArray.push(1);
return myArray;
};
}
let newArray = expandArray();
console.log(newArray());
Note this is my first contribution on stack overflow.

Passing JavaScript arrays to functions

A general question on JavaScript. If I have a function which modifies an array, such as:
var some_array = [];
function a_function(input, array){
//do stuff to array
return array;
}
In most languages:
var some_array = [];
some_array = a_function(input, some_array);
console.log(some_array);
works, however in js the below works as well:
var some_array = [];
a_function(input, some_array);
console.log(some_array);
Is this correct and how is this working?
Arrays in JS are objects and are passed into functions by value, where that value is a reference to the array. In other words, an array passed as an argument to a function still points to the same memory as the outer array.
This means that changing the array contents within the function changes the array passed from outside the function.
function f(arr) {
arr.push(1);
return arr;
}
var array = [];
// both function calls bellow add an element to the same array and then return a reference to that array.
// adds an element to the array and returns it.
// It overrides the previous reference to the array with a
// new reference to the same array.
array = f(array);
console.log(array); // [1]
// adds an element to the array and ignores the returned reference.
f(array);
console.log(array); // [1, 1]

Work with returned array from function

I'm trying to return an array from a function and work with its results.
When I just want to get its length, I always get a 0:
function myFunc() {
var arr = [];
arr.push("test");
arr.push("another test");
return arr;
}
alert(myFunc.length) // expected 2, but got 0
Here is a fiddle.
You need to call it as myfunc().length because you are calling a function.
Remember you are calling a function, so the parameter list (even if empty) must be given to the call, try:
alert(myFunc().length)
You have to call the function like so
function myFunc() {
var arr = [];
arr.push("test");
arr.push("another test");
return arr;
}
alert(myFunc().length)
https://jsfiddle.net/n5xdcrzm/
Function.length, The length property specifies the number of arguments expected by the function.
And that is the reason you could get 0 in alert as you are reading length property of the function-object
If you are expecting 2, which is length of the array, you need to invoke the function.
function myFunc returns the array in which 2 items are being pushed.
Invoke the function and read the length property of the returned array
function myFunc() {
var arr = [];
arr.push("test");
arr.push("another test");
return arr;
}
alert(myFunc().length);

Dynamically instantiate class in javascript

I checked out this reference link and ended up using Matthew's solution, as it works for me.
var factory ={};
factory.Tree = function(arg1,arg2,arg3,arg4){
console.log(arg1+""+arg2+""+arg3+""+arg4);
}
function instantiate(classname){
return new (function(a){ return factory[classname].apply(this,a);})(Array.prototype.splice.call(arguments,1));
// also is this ^^^ a good practice? instead of declaring the temp function beforehand
// function t(a) {return factory[classname].apply(this,a);}
// return new t(Array.prototype.splice.call(arguments,1));
}
var newObj = instantiate("Tree",1,2,3,4); // this prints 1234 --> works
Though, I'm not sure why using user123444555621's solution only works if I pass in "arguments" (that is everything including "classname"):
function instantiate(classname){
return new (Function.prototype.bind.apply(factory[classname], arguments));
}
var newObj = instantiate("Tree",1,2,3,4); // this prints 1234 --> works
but if I slice "arguments" and remove "classname", then pass in the result array, it does not work as expected:
function instantiate(classname){
var args = Array.prototype.splice.call(arguments,1);
// ^^ I checked and this prints 1,2,3,4 as well
return new (Function.prototype.bind.apply(factory[classname], args));
}
var newObj = instantiate("Tree",1,2,3,4); // this prints 234undefined
I'm not sure why but somehow it seems like the args array is sliced (again) and removes its first element (1 in this case).
Could someone offer any insights? Thanks
Did you use the right array function slice vs splice ?
Array.prototype.slice() - Creates a new array from elements of an existing array. It does not modify the original array.
Array.prototype.splice() – Deletes and/or inserts elements in an array. Unlike slice(), the splice() method modifies the original array
and returns a new array. The splice() method takes three arguments.
Your problem is this line
var args = Array.prototype.splice.call(arguments,1);
You have essentially removed the first item from the arguments while turning it into array args
simply replace 1 by 0
var args = Array.prototype.splice.call(arguments,0);
DEMO
var factory ={};
factory.Tree = function(arg1,arg2,arg3,arg4){
console.log(arg1+""+arg2+""+arg3+""+arg4);
}
function instantiate(classname){
var args = Array.prototype.splice.call(arguments,0);
return new (Function.prototype.bind.apply(factory[classname], args));
}
instantiate("Tree",1,2,3,4);

Jquery function consumes the array

I don't quite understand what's wrong with my function that I wrote,
When I pass an array to it, eg:
var pvars=['health/1/1.jpg','health/1/2.jpg','health/1/3.jpg','health/1/4.jpg'];
cache_threads(pvars,1);
Then I end up with an empty variable, eg:
alert(pvars);
Returns an empty string.
Here is my function:
var cache_threads=function (arruy,quant){
if (quant==undefined) quant=1;
var div=Math.ceil(arruy.length/quant);
var a = arruy;
while(a.length) {
cache_bunch(a.splice(0,div));
}
}
a and arruy are the same array.
When you .splice one, you'll be splicing the other one, too!
If you want a (shallow) copy of the array, use .slice():
var a = arruy.slice(0);

Categories