Arguments Optional FreeCodeCamp Challenge - javascript

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 :)

Related

Functions console.log not good

I came across this exercice on the code academy and I don't understand why my code does not work. can someone explain to me and help me? thank you so much!
Here we have a function, addTwo(), that adds 2 to whatever is passed into it. Below that, we’ve created what will be a higher-order function, checkConsistentOutput(). The purpose of the higher-order function will be to check the work of addTwo(). Let’s get started!
To begin, inside the body of checkConsistentOutput(), declare two variables: checkA and checkB:
checkA stores the sum val plus 2.
checkB stores the invocation of the func callback, with val as the argument.
Next, below the variables, write a conditional statement that checks if the value of checkA is equal to the value checkB. If true, return the result of the callback function. If false, return the string 'inconsistent results'.
Finally, using console.log(), log the invocation of checkConsistentOutput() with two arguments: the addTwo() function and any number.
THIS IS MY CODE:
const addTwo = num => {
return num + 2;
}
const checkConsistentOutput = (func, val) => {
let checkA = val + 2;
let checkB = func(val)
if (checkA === checkB) {
return func(val);
} else {
return 'inconsistent results';
}
}
console.log(addTwo(5));
I can't pass the number 3 dunno why?
You have to include checkConsistentOutput() in the log, eg:
console.log(checkConsistentOutput(addTwo, 5));

tried to recreate the _.once function but only works upon at least 2 iterations not one

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

JavaScript function: what does this do?

I have been looking at this code for sometime now, trying to understand what it does but I can't really get my head around it. I need help with understanding what this function actually does
function element(array, gen) {
if(gen === undefined) {
gen = fromTo(
0,
array.length
);
}
return function() {
var index = gen();
if(index !== undefined) {
return array[index];
}
};
}
function concat(...gens) {
var next = element(gens),
gen = next();
return function recur() {
var value = gen();
if(value === undefined) {
gen = next();
if(gen !== undefined) {
return recur();
}
}
return value;
};
}
element is not a javascript built-in which means it must be defined elsewhere. Without knowing its function, it is impossible to say exactly what is happening, but here is what I can tell you.
concat takes n arguments of the same type. Without knowing what element does I can't tell you what type that is, but it can take as many as you need to give it. That is what the spread operator ... is telling you.
It returns a function that takes 0 arguments. When called, it continues to call itself checking if the return value of gen() is defined, if it is not, it changes gen to be the return value of next() and calls gen() again. It repeats this process until the return value of gen() is defined, and then returns that value.
Using it would look something like this.
var recur = concat(a,b,c,d,e); // can take any number of arguments of the same type
var someValue = recur(); // calls itself until it has a value to return
console.log(someValue); // use the value

Closure returns what is supposed to and also undefined

I'm practicing closures and my assigment for now is to :
Write a function once that accepts a callback as input and returns a function.
When the returned function is called the first time, it should call the callback
and return that output. If it is called any additional times, instead of calling
the callback again it will simply return the output value from the first time it
was called.
My callback is:
const addByX = function (num1) {
let number = num1;
function adding(num2) {
console.log(number + num2);
}
return adding;
}
//addByX(2)(8);
let addByTwo = addByX(2);
And my main function is:
const once = function (func) {
let isFirst = true;
let firstOutput;
function inside(numberToPass) {
if (isFirst) {
firstOutput = func(numberToPass);
isFirst = false;
return func(numberToPass);
} else {
return firstOutput;
}
}
return inside;
}
It works, but when I invoke it
const onceFunc = once(addByTwo);
console.log(onceFunc(4)); //should log 6
console.log(onceFunc(10)); //should log 6
it returns my values and also undefined.
And I really can't understand why would it.
Maybe if it works I should not ask this kind of questions, but I'm really curious.
Debugger couldn't clearly answer my question.
I'm suspicious it has something to do with console.log, as abvious as it looks.
Here in JS Bin
The function addByX returns another function, adding. But adding doesn't return anything; it just logs. It's return value is undefined.
I think you intended it to look like this:
const addByX = function (num1) {
let number = num1;
function adding(num2) {
return number + num2;
}
return adding;
}
So the reason that it "worked" is because the callback was printing to the console, rather than where you are invoking it.

Create a function with an undetermined number of successive calls

As part of a programming challenge, we are tasked with creating a function with an undetermined number of successive calls. As an example, let's say the function returns simply the sum of the provided arguments, it should work as follows :
sum(4)() // 4
sum(4)(5)() // 9
sum(4)(5)(9)() // 18
sum(4)(5)(9)(1)() // 19
// etc...
The problem is simplified by the allowed empty function call at the end as an indication of end of calls.
I have worked on a solution that does the job but using global variables inside the function itself :
var sum = function (a) {
if (!sum.init) {
sum.total = 0;
sum.init = true;
}
if (!arguments.length) {
sum.init = false;
return sum.total;
}
sum.total += a;
return sum;
};
This solution works but uses state, global variables and function object trickery which is not ideal. My question here is whether there is a way to solve the problem in a purely recursive way.
As a side note, I do not believe the problem can be solved if that last empty call () is not provided, but if I'm wrong please let me know.
Update
This issue has been answered in CodeReview : https://codereview.stackexchange.com/a/153999/129579
A neet solution that does not rely on global scope and is purely functional.
You can make use of closures to acheive what you want like this:
function sum(value){
// the closure variable that will be accessible for all the _sum calls (initialised to 0 for every sum call).
var result = 0;
// the function that will be returned (sum will only get called once to initialize the result to 0. It's _sum which will be returned as much as possible)
function _sum(a){
// if we passed a parameter, then add it to result and return a new _sum
if(typeof a != "undefined"){
result += a;
return _sum;
}
// if we didn't return the result
else
return result;
}
// of course after initializing result we need to call _sum that handle the actual summing and return whatever it returns (if value is defined, it will return another `_sum` if not it will return the value of result which will be 0 at first) from now on sum will have nothing to do with the rest of the calls (()()()... )
return _sum(value);
}
console.log("sum() = " + sum());
console.log("sum(7)() = " + sum(7)());
console.log("sum(5)(6)(7)() = " + sum(5)(6)(7)());
// will return 0 because we call sum again
console.log("sum() = " + sum());
NOTE: That sum(1)(7)(3)()); will call, in this order:
sum with the parameter 1 which will initialize result to 0 and call
_sum with the same parameter 1 which will add it to result and return a new inctance of _sum which will be called so the following
_sum get called with the parameter 7, add it and return a new _sum so the new
_sum get called with the parameter 3, ... spawn another
_sum that will have no parameter, therefore if(typeof a != "undefined") will fail and this _sum will return result instead.
The actual sum is only called once at the begining to do the initialization. It's, as I said, _sum that get chained after that all the way to the end.
Basically you could use an outer function sum for the initial call and a closure over the starting value a and an inner function fn, which is repeatingly returned and only exited if arguments.length is equal to zero.
If a value b is supplied, the variable a gets updated and the inner function fn gets returned.
function sum(a) {
return function fn(b) {
if (!arguments.length) {
return a;
}
a += b;
return fn;
};
}
console.log(sum(1)());
console.log(sum(1)(2)());
console.log(sum(1)(2)(3)());
Edit for calling sum with no argument
function sum(a) {
return arguments.length ?
function fn(b) {
if (!arguments.length) {
return a;
}
a += b;
return fn;
} :
0;
}
console.log(sum());
console.log(sum(1)());
console.log(sum(1)(2)());
console.log(sum(1)(2)(3)());

Categories

Resources