Javascript function invoke with different invoke fashions [duplicate] - javascript

This question already has answers here:
How can I make var a = add(2)(3); //5 work?
(33 answers)
Closed 5 years ago.
I want to implement the function in javascript let say Add that should support bellow formats
add(a,b,c)
add(a)(b)(c)
add(a)(b,c)
add(a,b)(c)
All these should return a+b+c. Is it possible? if so how?

Whenever the function is run collect the arguments object parameters into an array, and check it's length. If the length of the array is 3 or greater sum the first 3 numbers using Array#reduce. If not, return the function.
function add() {
var args = []; // collect the arguments
function innerAdd() {
args.push.apply(args, arguments); // add the arguments to args
// if the length of args is under 3 return innerAdd, if not sum the first 3 numers
return args.length < 3 ? innerAdd : args.slice(0, 3).reduce(function(s, n) {
return s + n;
});
}
return innerAdd.apply(null, arguments); // invoke innerAdd with current arguments
}
var a = 1, b = 2, c = 3;
console.log(add(a,b,c));
console.log(add(a)(b)(c));
console.log(add(a)(b,c));
console.log(add(a,b)(c));

You can do something like
function add(){
let sum = 0;
for(let e of arguments) sum += e;
let ret = add.bind(null, sum);
ret.toString = () => sum;
ret.valueOf = () => sum;
return ret;
}
let x = +add(2, 3)(4)(11)
console.log(x, typeof x);

Related

How to create an array with 'a' repeated 'b' times [duplicate]

This question already has answers here:
Create an array with same element repeated multiple times
(25 answers)
Closed 2 years ago.
I am trying to create a function that takes in two vairables a and b, this function will create an array with variable a reapeated b times.
This is how far I have gone but It's not outputting th correct number of items in the array:
var createArr = function(a, b) {
// returns an array with variable a repeated b times.
if (typeof b == 'number') {
var arr = [];
for (var i = 0; i <= b; i++) {
arr.push(a);
};
}
return arr;
};
createArr("ready",3)
Easy:
function createArr(a, b) {
return Array(b).fill(a);
}
If you use <= and the value “3” for “b”, the loop will run once for 0, 1, 2, and 3. Oops, that’s 4 times.
Instead you want to use < so the loop will run once for 0, 1, then 2, and not for 3.
See also https://en.wikipedia.org/wiki/Fencepost_error
for loop, break will be < not <= because when <= for loop start with 0 and break when it 3 so loop 4 times when need to loop 3 times so need an use <
var createArr = function(a, b) {
// returns an array with variable a repeated b times.
if (typeof b == 'number') {
var arr = [];
for (var i = 0; i < b; i++) {
arr.push(a);
};
}
return arr;
};
console.log(createArr("ready",3));

How to fetch/ get all the arguments of the function?

With JavaScript we have arguments property that lets us get the arguments of the function. I generally do it this way
function sum(){
var agumentCount = arguments.length;
var count =0;
var sumArguments = [];
// Fetching the arguments
while(count != agumentCount){
sumArguments.push(arguments[count]);
count++;
}
// function logic -- neglect this
var data = 0;
for(var i=0; i<sumArguments.length;i++){
data+=sumArguments[i];
}
return data;
}
// Calling the function
sum(2,3);
sum(9,15,65,458748);
sum();
sum(1);
Is there better way of fetching the arguments, as this takes O(n), where n is the number of arguments for the function.
You can use this code it will not reduce complexity but it's much better approach to this kind of operation -
function sum() {
var arr = Array.from(arguments);
return arr.reduce(function(total, x) {
return total + x;
}, 0)
}
console.log(sum(1, 2, 3, 4, 5)); // 15
You could use ..., the spread operator to work with variable number of arguments:
function sum(...nums){ //The arguments are stored in the nums array.
var sum = 0;
nums.forEach(function(num){
sum+=num;
});
return sum;
}
sum(1,2,3,4,5,6); //21
Check this out for more information.
EDIT:
Use the reduce function for more concise and readable code:
function sum(...nums){
return nums.reduce(function(add,num){
return add+num;
});
}
sum(1,2,3,4,5,6); //21
You do not need to fetch the arguments.
You can check if the first argument is an array and loop through that array.
function sum() {
let array= [],
ans = 0;
// Array check.
if (arguments[0] instanceof Array)
array = arguments[0];
else array = arguments;
// Sum all from array
const max = array.length;
for (let i = 0; i < max; i++) {
ans += array[i];
}
return ans;
}
console.log(sum(1,2,3));
console.log(sum([4,5,6]));
console.log(sum());
console.log(sum(7,8));
arguments is like array because
1.it return item by index;
2.it has length property.
but actually it is not an array because it is not generated by constructor Array, therefor it doesn't inheritance the prototype functions of Array.
This is a defect for the design of JavaScript.
Lucky you can still "borrow" the prototype functions of Array to generate an actual array.
function a(){
var arr=Array.prototype.concat.apply(arguments);
}

What is the best way to sum arrays using ECMASCRIPT 6 Generator/Functions

Is there a better way instead of adding values of arrays up using a generator function as closure?
var sumArrays = function(){
var sum = 0;
return function*(){
while(true){
var array = yield sum;
if(array.__proto__.constructor === Array){
sum += array.reduce(function(val,val2){ return val+val2; });
}
else sum=0;
}
};
};
var gen = sumArrays();
// is this step required to make a generator or could it be done at least differently to spare yourself from doing this step?
gen = gen();
// sum some values of arrays up
console.log('sum: ',gen.next()); // Object { value=0, done=false}
console.log('sum: ',gen.next([1,2,3,4])); // Object { value=10, done=false}
console.log('sum: ',gen.next([6,7])); // Object { value=23, done=false}
// reset values
console.log('sum: ',gen.next(false)); // Object { value=0, done=false}
console.log('sum: ',gen.next([5])); // Object { value=5, done=false}
This doesn't seem to be a problem generators are supposed to solve, so I would not use a generator here.
Directly using reduce (ES5) seems to be more appropriate:
let sum = [1,2,3,4].reduce((sum, x) => sum + x);
As a function:
function sum(arr) {
return arr.reduce((sum, x) => sum + x);
}
If you really want to sum multiple arrays across multiple function calls, then return a normal function:
function getArraySummation() {
let total = 0;
let reducer = (sum, x) => sum + x;
return arr => total + arr.reduce(reducer);
}
let sum = getArraySummation();
console.log('sum:', sum([1,2,3])); // sum: 6
console.log('sum:', sum([4,5,6])); // sum: 15
Keep it simple.
Here is use of for/of loop and arrow function,
const sumArray = myArray => {
let sum = 0;
for(const value of myArray)
sum+= value;
return sum;
}
const myArray = [1, 2, 5];
console.log(sumArray(myArray));

Currying with functions that take unlimited arguments

Lets say i have the following add function that takes an unlimited number of arguments.
function add () {
var total = 0;
var args = Array.prototype.slice.call(arguments, 0);
for (var i=0; i<args.length; i++) {
total += arguments[i];
}
return total;
}
and the following curry function.
function curryFunction(orig_func) {
var ap = Array.prototype;
var args = arguments;
function fn() {
if (arguments.length != 0) {
ap.push.apply(fn.args, arguments);
return fn;
} else {
return orig_func.apply(this, fn.args);
}
};
return function() {
fn.args = ap.slice.call( args, 1 );
return fn.apply( this, arguments );
};
}
I then want to do something like:
var f = curryFunction(add);
var a = f(3)(4)(3);
var b = f(10)(3);
var result1 = a(); // returns 10
var result2 = b(); // returns 13
However i always get 13 for both a() and b() i assume is because in line
fn.args = ap.slice.call(args, 1);
the existing array [3,4,3] is overwriting with []. Can someone please provide me with a hint on how to make this work? Thanks
The problem is that fn is scoped to curryFunction and so is shared between a and b.
All you have to do is move the definition of fn into the anonymous return function. It's then created when you call f, and the problematic fn.args = line is only called once.
Proof: jsFiddle.
Currying a function which takes indefinitely many arguments can be implemented as follows;
Lets say we have a function called addAll() which returns the sum of all provided arguments.
var addall = (...a) => a.reduce((p,c) => p + c);
And we have a curry function which takes a function and returns curried version ad infinitum up until the returned function is called with no arguments, only when the result of all previously provided arguments will be returned. OK here is the curry function.
var curry = f => (...a) => a.length ? curry(f.bind(f,...a))
: f();
Lets see it in action;
var addAll = (...a) => a.reduce((p,c) => p + c),
curry = f => (...a) => a.length ? curry(f.bind(f,...a)) : f(),
curried = curry(addAll),
result = curried(10,11)(10)(37)(10,17,42)();
console.log(result);
result = curried("a","b")("c")("d")("e","f","g")();
console.log(result);

array to an array of functions [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Javascript closure inside loops - simple practical example
You have an array of arbitrary values. Write a transform function in the global scope that will transform the array to an array of functions that return the original values, so instead of calling a[3], we will call a3.
For example I want:
var a = ["a", 24, { foo: "bar" }];
var b = transform(a);
a[1]; // 24
b[1](); // 24
However I am getting:
b
[function () {
return this.temp;
}, function () {
return this.temp;
}, function () {
return this.temp;
}]
Here is my code:
var a = ["a", 24, { foo: "bar" }];
var b = transform(a);
document.writeln(a[1]); // 24
document.writeln(b[0]()); // 24
document.writeln(b[1]()); // 24
function transform(array) {
b = [];
var i;
for (i = 0; i < array.length; i += 1) {
b[i] = function () {
return temp;
};
}
return b;
}
function transform(array) {
b = [];
var i;
for (i = 0; i < array.length; i += 1) {
b[i] = (function (x) {
return function () { return x; };
})(array[i]);
}
return b;
}
demo http://jsbin.com/udasoj/1/edit
Your code is correct if you call b[0](), then you should get the value returned.
Note that none of the existing answers will quite work; they will all produce functions that return that last value in a. var is function-scoped and interacts poorly with closures.
See this other answer I just wrote, which explains a similar problem: https://stackoverflow.com/a/14330595/17875
What is temp? It looks like the way to accomplish this is to generate the function via another function:
function transform(array) {
b = [];
var i;
for (i = 0; i < array.length; i += 1) {
b[i] = createReturnFunction(a[i]);
};
}
return b;
}
function createReturnFunction(value){
return function(){ return value; };
}
Working Fiddle: http://jsfiddle.net/eFWyf/

Categories

Resources