I want pass quiz from codewars - https://www.codewars.com/kata/53cf7e37e9876c35a60002c9/train/javascript, but I can not avoid an error to pass :"TypeError: add(...) is not a function"
function curryPartial(){
let args= [...arguments]
let fn = args[0]
console.log(fn.length)
function cur(){
let argsCur= [...arguments]
return curryPartial(...args,...argsCur)
}
cur.valueOf = ()=>{
//return args.reduce((a,b)=>a+b)
// console.log(...args)
// const res = +fn(...args.slice(1))
// return res
}
return cur
}
function add(a, b, c) {
return a + b + c;
}
console.log(+curryPartial(add(1,2)(3)))
How I can avoid this error to pass the quiz ?
That's about the add(1,2)(3)
Of cause you get errors, the add function returns a value, by doing add(1,2)(3) you are executing the return value of add(1,2) with passing a 3, which is not a function, so the error has been raised.
the execute statement should be
console.log(+curryPartial(add)(1,2)(3))
// not
console.log(+curryPartial(add(1,2)(3)))
pay attention to the parentheses pair
Related
in need of help with a codecamp challenge:
Arguments Optional - The challenge
https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures/intermediate-algorithm-scripting/arguments-optional
My Question
I know this can be done with the arguments object (see figure 1), where I can call the function again when the second value is undefined so I've gone for a different approach; However, my code of using currying works but becomes an issue with 'addTogether(5)(7);'
Issue ->
I get the returned value of 12 but doesn't get approved in the code challenge.
I did originally return the value inside the sum function but the challenge required the sum value to be returned in addTogether function, which I did so now it resulting in the following
addTogether(2,3); // now working
addTogether(5)(7); // NOT working
addTogether(23, 30); // now working
Is there something I'm doing wrong that's resulting in the test case failing even though the correct value is returned?
let val = 0;
function sum(a, b) {
val = a + b;
}
function sumTwoAnd(sumFunc) {
return function addTogether(...params) {
let numsArr = [...params];
const res = numsArr.every(el => typeof el === 'number');
if (res === false) return;
if (numsArr.length >= sumFunc.length) {
sumFunc(...numsArr);
} else {
return function(...args2) {
let newArr = numsArr.concat(args2);
addTogether(...newArr);
}
}
console.log(val);
return val;
}
}
let addTogether = sumTwoAnd(sum);
addTogether(2,3);
addTogether(5)(7);
addTogether(23, 30);
Figure 1
Shows how I can get 'test(5)(7)' the second parameter from the function
function test() {
const [f, s] = arguments;
console.log(f, s)
if (s === undefined) {
return s => test(f, s)
}
}
test(23, 30);
test(5)(7);
You declared addTogether using let, so the declaration won't be hoisted above the point where it was defined. This is making your recursive call in the else statement fail, since addTogether() doesn't exist that far up.
You might want to extract the function you're returning in sumTwoAnd() as a separate function definition, so it can freely call itself, similar to your Figure 1 example.
Or you can call sumTwoAnd() instead to regain the function, then pass newArr to said function.
Instead of calling the function I have now returned it...
return addTogether(...newArr);
This now works :)
onceCopy function (testFunc) {
const copyFunc = (a) => {
const copyFunc2 = (b) => {
return testFunc(a);
};
return copyFunc2;
};
return copyFunc;
};
So the function returns the inner function upon first invocation.
Then returns the inner function of the inner function of the second invocation.
Then the second inner function (third invocation) actually returns the passed argument in the parent function and only invokes it with the character we gave it on the second invocation.
Ideally I want to achieve what I'm achieving over many invocations after only the first one if that makes sense.
Edit: Yes sorry, _.once.
Edit: so first invocation onceCopy SHOULD hold a copy of the Func passed
Second invocation SHOULD trigger the copy and gives an ouput
Third invocation SHOULD give the result of the second invocation so should the fourth, fifth, sixth and so on...
My function does do this, but on the second invocation it stores a function (copyFunc2) again, but I just made that because I need somewhere to store "a".
so like we have
function multiplyBy3 (a) {return a*3}
and then once copy stores a copy of multiplyBy3
const actualFunction = onceCopy(multiplyBy3)
then upon second and third invocation what I want
actualFunction(1) = 3
actualFunction(66) = 3
so the passed function ONLY RUNS ONCE
Cant explain more than this, its in the lodash docs.
I'm not familiar with the function you're trying to reimplement, so feel free to correct me if I misunderstood. To wrap a function and ensure it's only called once you don't need multiple nested wrappings, only one with some state.
You need to keep track of whether you already have a result to return (hasResult) and if so, what that result is (result). Keeping these two variables separate allows you to cover the case when result is undefined while keeping the code easy to read and understand.
function once(wrappedFunction) {
let hasResult = false;
let result;
return (...args) => {
if (hasResult) {
return result;
}
result = wrappedFunction.apply(this, args);
hasResult = true;
return result;
}
}
// An example function to wrap
function multiply(a, b) {
return a * b;
}
const demoFunction = once(multiply)
console.log(demoFunction(1, 2)); // 2
console.log(demoFunction(3, 4)); // 2
console.log(demoFunction(5, 6)); // 2
Is this what you were looking for?
The initial function return is kept on subsequent calls. I used a second variable called in case the first call returns undefined, which should also be returned on subsequent calls.
const once = (onceFn) => {
let called;
let value;
return (...args) => {
if (called) return value;
called = true;
return (value = onceFn(...args));
};
};
function multiplyBy3(a) {
return a * 3;
}
const fn = once(multiplyBy3);
console.log(fn(3)); // 9
console.log(fn(66)); // 9
After calling the function for the 1st time, and getting the result, create a new function that returns the result, and use it whenever the wrapped function is called:
const once = fn => {
let func
return (...args) => {
if(func) return func()
const result = fn(...args)
func = () => result
return result
}
}
const multiply = (a, b) => a * b
const demoFunction = once(multiply)
console.log(demoFunction(1, 2)); // 2
console.log(demoFunction(3, 4)); // 2
console.log(demoFunction(5, 6)); // 2
I was wondering why a console.log command, right after a return command, doesn't work.
Here's an example. Shouldn't the console.log(square(50)) execute all the commands in the function body?
With this code, the console.log commands only displays the number 2500, but it doesn't display the phrase "This is the square of it". Why?
function square(x) {
return x * x;
console.log(`This is the square of it`);
}
console.log(square(50));
Because return make the function return immediately, any code written after is totally ignored.
console.log cannot bypass this behaviour.
This is basic programming knowledge, the explanation here will be kept "simple" for the target audience.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/return
The return statement ends function execution and specifies a value to
be returned to the function caller.
The purpose is the return is actually allowing the function to provide some form of information. When the return is reached, the code execution will typically go back to where the function was called from and evaluate to the return value, then continue execution from there:
function sum(a, b) {
return a + b;
}
const result = sub(3, 2); // Returns 5
console.log(result); // Outputs 5.
console.log(sum(2, 2)); // Outputs 4
Additionally:
function calculate(a, b, operation) {
const addOperations = ["add", "sum", "plus"];
const subtractOperations = ["take", "subtract", "minus"];
const multiplyOperations = ["times", "multiply"];
const divideOperations = ["divide", "divise"];
if (addOperations.includes(operation.toLowerCase())) return a + b;
if (subtractOperations.includes(operation.toLowerCase())) return a - b;
if (multiplyOperations.includes(operation.toLowerCase())) return a * b;
if (divideOperations.includes(operation.toLowerCase())) return a / b;
}
console.log(calculate(3, 3, "multiply")); // Outputs 9
console.log(calculate(4, 4, "divide")); // Outputs 1
console.log(1, 1, ""); // Outputs undefined
If there is no return, it evaluates to undefined.
Because return is a statement and any code written after return doesn't execute that's why console.log written after return statement doesn't execute. The output of above only will be 2500
console.log (This is the square of it); this line will be ignored
Because return ends the function , and the console log is ignored.
Instead of use 2 console.log you can use just 1 and call the function after , like this :
function square(x) {
let sq = x*x;
console.log(`This is the square of it: ${sq}`);
}
square(50);
The return statement ends the execution of function at that statement and no further lines will be executed as in your code.
So instead try this:
function square(x) {
return x * x;
}
console.log('This is the square of it: ', square(50));
I'm trying to implement currying function:
function sum(a, b, c) {
console.log('SUM'+JSON.stringify(arguments))
return a + b + c;
}
var curry= function (func,...n) {
return function(...args2) {
//console.log('arg2s'+args2)
return func.apply(this,n.concat(args2));
};
}
curry(sum,1,2)(3) //SUM{"0":1,"1":2,"2":3}, O/P:6
Above gives correct output, but i am not getting the necessity to use apply.
So, if i change my function to below:
var curry= function (func,...n) {
return function(...args2) {
//console.log('arg2s'+args2)
return func(n.concat(args2));
};
}
curry(sum,1,2)(3) //SUM{"0":[1,2,3]} O/P:"1,2,3undefinedundefined"
I basically have two questions here:
Why is the implementation of curry not working when calling func directly?Why is the output such weird ?
2.How do i change my function in a way that i can call it as below and should return sum:
curry(1)(2)(3)/curry(1,2)(3)/curry(1,2,3) etc instead of the way i'm calling currently.
I could find some solutions on the web, but couldn't understand .
ex:
function curry(func) {
return function curriedFunc(...args) {
if (args.length >= func.length) {
return func.apply(this, args);
} else {
return function(...args1) {
return curriedFunc.apply(this, args.concat(args1));
}
}
};
}
Any help would be highly appreciated !!
Your func accepts three arguments: a, b, and c. When you do:
return func(n.concat(args2));
you're passing it one argument, an array. It's equivalent to:
const arr = n.concat(args2);
return func(arr);
Sounds like you'd want to spread the arguments into the call of func instead:
return func(...n, ...args2)
With spread syntax, each item from the iterable is put into a parameter. Eg, if the n array has one item, it gets set as the first argument passed to func, and if args2 has 2 items, the first gets set as the second argument passed, and the second gets set as the third argument passed.
function sum(a, b, c) {
console.log('SUM' + JSON.stringify(arguments))
return a + b + c;
}
var curry = function(func, ...n) {
return function(...args2) {
return func(...n, ...args2);
};
}
curry(sum, 1, 2)(3);
How do i change my function in a way that i can call it as below and should return sum: curry(1)(2)(3)/curry(1,2)(3)/curry(1,2,3) etc
Keep track of the total number of arguments passed in a closure created the first time the function is called. In the returned function, push all arguments to the array, and if the array's length is 3, return the sum, otherwise return the function again:
function sum(a, b, c) {
return a + b + c;
}
var curry = function(func, ...argsSoFar) {
const neededArgs = func.length;
const returnedFn = (...args) => {
argsSoFar.push(...args);
if (argsSoFar.length === neededArgs) {
return func(...argsSoFar);
} else {
return returnedFn;
}
};
return returnedFn;
}
console.log(
curry(sum, 1, 2)(3),
curry(sum)(1, 2)(3),
curry(sum)(1)(2, 3),
curry(sum)(1)(2)(3),
);
Is there any way that I can write the function so that when I call it even by passing arguments differently, it still outputs the same value
I am new to JavaScript and was recently asked this question in an interview -
Write a function sum which when called like sum(2)(3) or sum(2, 3) should return 5.
This could be done individually as follows
function sum(a){
return function(b){
return a+b
}
}
or
function sum(a, b){
return a+b
}
If I follow the first code, it won't execute sum(a, b) and of course the second code will not support sum(a)(b). Is there any way that I can merge the two code snippets so that it executes doesn't matter how I call it ?
You'll need to check how many arguments were passed. If two are passed, return the added values; otherwise, return a function that, when called, returns its argument plus the closure's argument:
const sum = (...args) => {
if (args.length === 2) {
return args[0] + args[1];
}
return arg => arg + args[0];
};
console.log(sum(2)(3));
console.log(sum(2, 3));
More generally, you can create a makeSum function to handle when the total number of arguments to accept is an arbitrary number:
const makeSum = totalArgCount => {
const fn = (...args) => {
if (args.length === totalArgCount) {
return args.reduce((a, b) => a + b, 0);
}
return fn.bind(undefined, ...args);
};
return fn;
};
const sum2 = makeSum(2);
console.log(sum2(2)(3));
console.log(sum2(2, 3));
const sum4 = makeSum(4);
console.log(sum4(2)(3)(4)(5));
console.log(sum4(2, 3, 4)(5));
function sum(a, b) {
return b !== undefined ? (a + b) : function(b) { return a + b; }
}
console.log(sum(1,2));
console.log(sum(1)(3));
You can do it like this, by checking the b argument. If it is undefined, then you return a function. If it is not, you return the sum of the numbers.
Of course you could also check the both arguments are numbers, but this is simple version to illustrate what you want.