Check if a function takes an array or single valued input - javascript

I am attempting to write a function that takes an array and another function as an input. The only thing I know about the supplied function though is that it either
takes a single number argument and returns a new number or
takes an array of numbers and returns a new array of numbers.
In my function, I want to check whether it's the first or second case to determine whether or not to call the supplied function with Array.prototype.map().
So with these two functions...
var unknownFunction = function( unknownInput ) {
//Does stuff with input
//returns number or array of numbers...
return someValueOrValues
}
and
var mainFunction = function( anArray, preFunction ){
// SOME CODE TO CHECK IF ARG NEEDS TO BE NUMBER OR ARRAY
// ...
// ...
**ANSWER WOULD FIT HERE**
if( argIsNumber === true ){
// function takes NUMBER
anArray = anArray.map( preFunction )
}else{
// function takes ARRAY
anArray = preFunction(anArray)
}
// DO STUFF WITH ARRAY AFTER USER FUNCTION HAS MADE IT'S MODIFICATIONS
// ...
// ...
// ...
return anArray;
}
is there any way to poke inside the first function to figure out how best to call it?

Since JavaScript is a dynamically-typed language, function's input parameters have type once some calls it with some argument.
One elegant and possible approach is adding a property to the whole given function to hint the input parameter type:
var func = function() {};
func.type = "number"; // a function decorator
var mainFunction = function(anArray, inputFunc) {
if(typeof inputFunc != "function") {
throw Error("Please supply a function as 'inputFunc'!");
}
switch(inputFunc.type) {
case "number":
return anArray.map(preFunction);
case "array":
return preFunction(anArray);
default:
throw Error("Type not supported");
}
};
mainFunction([1,2,3], func);
When you work with dynamically-typed languages you need to think about coding using convention over configuration and/or using duck typing. Type safety provided by strongly-typed languages is replaced by a good documentation.
For example:
Provide a function as second parameter with a type property to tell
the mainFunction what's the expected type of the predicate
function.

I would use the try-catch approach but test the actual functions, and if one fails to try the next one.
Let's say these are your functions that are passed in as your unknow function. They each only modify a number by adding 1 to it.
function onlyTakesNumber(num) {
return num + 1;
}
function onlyTakesArray(arr) {
return arr.map(num => num + 1);
}
Now, here is your main function. The reason for the additional map inside of the try is to test to make sure you didn't get a string back if an array was passed to the onlyTakesNumber function. The additional test map will again reveal if the code needs to hop into the catch.
var mainFunction = function (anArray, preFunction) {
try {
// the map on the end checks to make sure you did not get a string back
anArray = preFunction(anArray).map(test => test);
}
catch (e) {
anArray = anArray.map(preFunction);
}
// Do whatever else with anArray
return anArray;
};
console.log(mainFunction([1, 2, 3], onlyTakesArray)); // [2, 3, 4]
console.log(mainFunction([7, 8, 9], onlyTakesNumber)); // [8, 9, 10]
Here is a JSFiddle you can test this on

The shortest answer is: "you can't".

Related

Problem of best practice with function return

I am new about programming. I have some difficulties to undurstand function.
So I done practice. But, I don't know why use return.
My code work.
In this exemple :
the function name is reverse.
I return in my function an array [1, 2, 5, 8].
Console.log a new array named reversed.
function reverse(array) {
const reversed = [];
for (i = array.length - 1; i > -1; i--) {
reversed.push(array[i]);
}
console.log(reversed);
}
return reverse([1, 2, 5, 8]);
**
But why after validate exercice, it's say me false and send me this solution :**
function reverse(array) {
const reversed = [];
for (let i = array.length - 1; i > -1; i--) {
reversed.push(array[i]);
}
return reversed;
}
Thanks : )
I googling and use chat GPT to teach me why use return in my case. But, nothing about I can understand.. I need your help.
Thank all.
The variable reversed is defined inside the function body so it can only be accessed from inside of the function. In your code you tried to access the variable from outside of the function. return keyword is used inside the function to return a value, using return outside the function has no effect.
Some remarks:
The names reverse and reversed are very similar which can lead to confusion. I see it happening in another answer and in your comments. reverse is defined as a function, and reversed is a local variable that references an array. They are completely different objects.
In your code you have placed a return statement where it is not valid. A return statement can only occur inside a function body.
console.log(reversed) will output the result in the console window, but that is not what the purpose is of the exercise. Although console.log is very useful while you are debugging your code, it is not equivalent to a return value. The caller of your function will get as return value what the function has returned with a return statement, not what console.log has output.
Your code does not define i with let (or var) and so it is implicitly declared as a global variable. This is not good practice. Always define variables explicitly.
Your code calls the reverse function. This is what you typically would do to test your function, but in code challenges, this call is typically made by the person or framework that tests your implementation. And those tests will call it more than once, with different arrays as argument, often including boundary cases, like an empty array, or a very large array.
So when you debug code, you would call the function and print the value that it returns, like so:
function reverse(array) {
const reversed = [];
for (let i = array.length - 1; i > -1; i--) {
reversed.push(array[i]);
}
return reversed;
}
let result = reverse([1,2,3,4]);
console.log(result); // Should be [4,3,2,1]
result = reverse([1]);
console.log(result); // Should be [1]
result = reverse([]);
console.log(result); // Should be []
result = reverse(reverse([1,2,3,4])); // Reversing the result!
console.log(result); // Should be [1,2,3,4]
Maybe I should also mention that reverse is also a native method available for arrays. It will reverse the array itself instead of creating a new array (like above). If the purpose is to always create a new array, you can still make use of it: first create a copy of the given array, reverse the copy and return that:
function reverse(array) {
// The spread syntax creates a copy, and reverse is applied on the copy
return [...array].reverse();
}
let result = reverse([1,2,3,4]);
console.log(result); // Should be [4,3,2,1]
result = reverse([1]);
console.log(result); // Should be [1]
result = reverse([]);
console.log(result); // Should be []
result = reverse(reverse([1,2,3,4])); // Reversing the result!
console.log(result); // Should be [1,2,3,4]

Debounce values but return all non unique elements instead of just one element in javascript [duplicate]

This question already has an answer here:
Lodash _.debounce with separate queues for unique argument variants
(1 answer)
Closed last year.
I have a use case where I have multiple functions firing simultaneously.
Each function can be called multiple times but I need to pick out only one return value. Im using debounce and it does work as intended. Even if I have 10 return values, I get only 1 return at the end. However if there are unique values, I want all the unique values returned
What is happening
-----1----2-----2---2----2----2----3-----3---3---3---3---3------>
(Only 1 value is returned)
-------------------3--------------------------------------------->
What I want
-----1----2-----2----2----2----2----3-----3---3---3---3---3------>
(Return all unique values)
-------------------1-------------------2--------------------3---->
What I have tried (Example)
var _ = require('lodash');
function printOne () {
handleDebounce(1);
}
function printTwo () {
handleDebounce(2);
}
function printThree () {
handleDebounce(3);
}
const handleDebounce = _.debounce((msg) => {
console.log(msg)
}, 2000, );
printOne();
printTwo();
printTwo();
printTwo();
printThree();
printThree();
printThree();
Output -> 3
Expected Output -> 1 2 3
Should I use a set to have a form of local cache and then get unique values? Any pointers would be welcome
You could keep track of all the arguments that were passed to the function. You could do this in a nested lookup Map, where each nested level is about a next argument (in case multiple arguments are passed). A special end-symbol indicates that an argument in that nested Map was the final argument -- to differentiate cases where the same arguments were passed, but with some extra arguments following those.
Here is how that could be implemented:
function withUniqueArguments(func, delay=50) {
const end = Symbol("end"); // A unique value only known here
const map = new Map; // Stores all argument references used before
function testAndSetArgs(args) {
let node = map;
for (const arg of args) {
let res = node.get(arg);
if (res === undefined) node.set(arg, res = new Map);
node = res;
}
let found = node.get(end);
if (!found) node.set(end, true);
return !!found;
}
return function wrapper(...args) {
if (testAndSetArgs(args)) return; // Function was called with these arguments before
setTimeout(() => func.call(this, ...args), delay);
};
}
const handleSearch = withUniqueArguments(console.log, 50);
handleSearch(1);
handleSearch(2);
handleSearch(2);
handleSearch(2);
handleSearch(3);
handleSearch(3);
handleSearch(3);
Disclaimer: the comparison of arguments is reference-based, so if objects are passed as arguments, they will only be regarded the same when they are really the same object, not copies of them. Also, when an object is mutated between calls, and passed again as argument, it will still be considered the same object, and so no second call will be made.
If you need copied objects to be considered the same, and mutated objects to be considered different, then you need to include a deep-object-comparison function.

Is it possible to add a value when returning a function from a recursive function being chained? [duplicate]

I'm trying to solve a puzzle, and am at my wit's end trying to figure it out.
I'm supposed to make a function that works like this:
add(1); //returns 1
add(1)(1); //returns 2
add(1)(1)(1); //returns 3
I know it can be done because other people have successfully completed the puzzle. I have tried several different ways to do it. This is my most recent attempt:
function add(n) {
//Return new add(n) on first call
if (!(this instanceof add)) {
return new add(n);
}
//Define calc function
var obj = this;
obj.calc = function(n) {
if (typeof n != "undefined") {
obj.sum += n;
return obj.calc;
}
return obj.sum;
}
//Constructor initializes sum and returns calc(n)
obj.sum = 0;
return obj.calc(n);
}
The idea is that on the first call, a new add(n) is initialized and calc(n) is run. If calc receives a parameter, it adds n to sum and returns itself. When it eventually doesn't receive a parameter, it returns the value of sum.
It makes sense in theory, but I can't get it to work. Any ideas?
--edit--
My code is just the route I chose to go. I'm not opposed to a different approach if anyone can think of one.
To answer "how dow this work". Given:
function add(n) {
function calc(x) {
return add(n + x);
}
calc.valueOf = function() {
return n;
}
return calc;
}
var sum = add(1)(2)(3); // 6
When add is called the first time, it stores the value passed in in a variable called n. It then returns the function calc, which has a closure to n and a special valueOf method (explained later).
This function is then called with a value of 2, so it calls add with the sum of n + x, wich is 1 + 2 which 3.
So a new version of calc is returned, this time with a closure to n with a value of 3.
This new calc is called with a value of 3, so it calls add with n + x, which this time is 3 + 3 which is 6
Again add returns a new calc with n set to 6. This last time, calc isn't called again. The returned value is assigned to the variable sum. All of the calc functions have a special valueOf method that replaces the standard one provided by Object.prototype. Normally valueOf would just return the function object, but in this case it will return the value of n.
Now sum can be used in expressions, and if its valueOf method is called it will return 6 (i.e. the value of n held in a closure).
This seems pretty cool, and sum will act a lot like a primitve number, but it's actually a function:
typeof sum == 'function';
So be careful with being strict about testing the type of things:
sum * 2 // 12
sum == 6 // true
sum === 6 // false -- oops!!
Here's a somewhat streamlined version of #RobG's great answer:
function add(n) {
function calc(x) { return n+=x, calc; }
calc.valueOf = function() { return n; };
return calc;
}
The minor difference is that here calc just updates n and then returns itself, rather than returning itself via another call to add, which puts another frame on the stack.
Making self-replication explicit
calc is thus a pure self-replicating function, returning itself. We can encapsulate the notion of "self replication" with the function
function self_replicate(fn) {
return function x() {
fn.apply(this, arguments);
return x;
};
}
Then add could be written in a possibly more self-documenting way as
function add(n) {
function update(x) { n += x; }
var calc = self_replicate(update);
calc.valueOf = function() { return n; };
return calc;
}
Parallel to Array#reduce
Note that there is a certain parallelity between this approach to repeatedly calling a function and Array#reduce. Both are reducing a list of things to a single value. In the case of Array#reduce the list is an array; in our case the list is parameters on repeated calls. Array#reduce defines a standard signature for reducer functions, namely
function(prev, cur)
where prev is the "accumulator" (value so far), cur is the new value being fed in, and the return value becomes the new value the accumulator. It seems useful to rewrite our implementation to make use of a function with that kind of signature:
function add(n) {
function reducer(prev, cur) { return prev + cur; }
function update(x) { n = reducer(n, x); }
var calc = self_replicate(update);
calc.valueOf = function() { return n; };
return calc;
}
Now we can create a more general way to create self-replication-based reducers based on a reducer function:
function make_repeatedly_callable_function(reducer) {
return function(n) {
function update(x) { n = reducer(n, x); }
var calc = self_replicate(update);
calc.valueOf = function() { return n; };
return calc;
};
}
Now we can create add as
var add = make_repeatedly_callable_function(function(prev, cur) { return prev + cur; });
add(1)(2);
Actually, Array#reduce calls the reducer function with third and fourth arguments, namely the index into the array and the array itself. The latter has no meaning here, but it's conceivable we might want something like the third argument to know what "iteration" we're on, which is easy enough to do by just keeping track using a variable i:
function reduce_by_calling_repeatedly(reducer) {
var i = 0;
return function(n) {
function update(x) { n = reducer( n, x, i++); }
var calc = self_replicate(update);
calc.valueOf = function() { return n; };
return calc;
};
}
Alternative approach: keeping track of values
There are certain advantages to keeping track of the intermediate parameters the function is being called with (using an array), and then doing the reduce at the end instead of as we go along. For instance, then we could do Array#reduceRight type things:
function reduce_right_by_calling_repeatedly(reducer, initialValue) {
var array_proto = Array.prototype,
push = array_proto.push,
reduceRight = array_proto.reduceRight;
return function(n) {
var stack=[],
calc = self_replicate(push.bind(stack));
calc.valueOf = reduceRight.bind(stack, reducer, initialValue);
return calc(n);
};
}
Non-primitive objects
Let's try using this approach to build ("extend") objects:
function extend_reducer(prev, cur) {
for (i in cur) {
prev[i] = cur[i];
}
return prev;
}
var extend = reduce_by_calling_repeatedly(extend_reducer);
extend({a: 1})({b: 2})
Unfortunately, this won't work because Object#toValue is invoked only when JS needs a primitive object. So in this case we need to call toValue explicitly:
extend({a: 1})({b: 2}).toValue()
Thanks for the tip on valueOf(). This is what works:
function add(n) {
var calc = function(x) {
return add(n + x);
}
calc.valueOf = function() {
return n;
}
return calc;
}
--edit--
Could you please explain how this works? Thanks!
I don't know if I know the correct vocabulary to describe exactly how it works, but I'll attempt to:
Example statement: add(1)(1)
When add(1) is called, a reference to calc is returned.
calc understands what n is because, in the "mind" of the interpreter, calc is a function child of add. When calc looks for n and doesn't find it locally, it searches up the scope chain and finds n.
So when calc(1) is called, it returns add(n + x). Remember, calc knows what n is, and x is simply the current argument (1). The addition is actually done inside of calc, so it returns add(2) at this point, which in turn returns another reference to calc.
Step 2 can repeats every time we have another argument (i.e. (x)).
When there aren't any arguments left, we are left with just a definition of calc. The last calc is never actually called, because you need a () to call a function. At this point, normally the interpreter would return a the function object of calc. But since I overrode calc.valueOf it runs that function instead.
When calc.valueOf runs, it finds the most recent instance of n in the scope chain, which is the cumulative value of all previous n's.
I hope that made some sense. I just saw #RobG 's explanation, which is admittedly much better than mine. Read that one if you're confused.
Here's a variation using bind:
var add = function _add(a, b) {
var boundAdd = _add.bind(null, a + b);
boundAdd.valueOf = function() {
return a + b;
}
return boundAdd;
}.bind(null, 0);
We're taking advantage of a feature of bind that lets us set default arguments on the function we're binding to. From the docs:
bind() also accepts leading default arguments to provide to the target
function when the bound function is called.
So, _add acts as a sort of master function which takes two parameters a and b. It returns a new function boundAdd which is created by binding the original _add function's a parameter to a + b; it also has an overridden valueOf function which returns a + b (the valueOf function was explained quite well in #RobG's answer).
To get the initial add function, we bind _add's a parameter to 0.
Then, when add(1) is called, a = 0 (from our initial bind call) and b = 1 (passed argument). It returns a new function where a = 1 (bound to a + b).
If we then call that function with (2), that will set b = 2 and it'll return a new function where a = 3.
If we then call that function with (3), that will set b = 3 and it'll return a new function where a = 6.
And so on until valueOf is called, at which point it'll return a + b. Which, after add(1)(2)(3), would be 3 + 3.
This is a very simple approach and it meets the criteria the OP was looking for. Namely, the function is passed an integer, keeps track of that integer, and returns itself as a function. If a parameter is not passed - the function returns the sum of the integers passed to it.
let intArray = [];
function add(int){
if(!int){
return intArray.reduce((prev, curr) => prev + curr)
}
intArray.push(int)
return add
}
If you call this like so:
console.log(add(1)(1)());
it outputs 2.

Confused about the `return` statement in javascript. Explanation needed

I posted a question not too long ago this morning regarding a kata that I was trying to solve. In that question, (found here if interested Kata Question) I needed to add a return statement to my function so that I would avoid the following error Value is not what was expected.
Now I have my second iteration of my kata solution to try out and here it is:
function isMerge(s, part1, part2) {
var pointer = 0
splitString = s.split('');
splitString.forEach(function(character) {
if (part1.includes(character) || part2.includes(character)) {
pointer++;
return true;
} else {
return false;
}
});
}
isMerge('codewars','cdw','oears')
I am still getting Value is not what was expected errors when I try to execute the code and this time I'm confused as to why in particular this happens.
For starters, taken from the MDN guide
The return statement ends function execution and specifies a value to be returned to the function caller.
expression
The expression to return. If omitted, undefined is returned instead.
Look at my if/else logic I am specifying a return true and return false condition in my forEach loop to see if all the chars from part1 and part2 are in the string. I am returning something so why is it that I have a Value is not what was expected?.
Second of all, by definition of the return statement, the function is supposed to stop when it reaches that keyword. However, when I place a console.log(character) in the logic, I can see on my console that all of the characters are being outputted so the function is not breaking at all when return true is executed. Why is that?
Third, I am confused as to when to use the return keyword in general. Consider these examples from the MDN docs for ForEach.
Example 1:
function logArrayElements(element, index, array) {
console.log('a[' + index + '] = ' + element);
}
// Notice that index 2 is skipped since there is no item at
// that position in the array.
[2, 5, , 9].forEach(logArrayElements);
// logs:
// a[0] = 2
// a[1] = 5
// a[3] = 9
Example 2:
function Counter() {
this.sum = 0;
this.count = 0;
}
Counter.prototype.add = function(array) {
array.forEach(function(entry) {
this.sum += entry;
++this.count;
}, this);
// ^---- Note
};
var obj = new Counter();
obj.add([2, 5, 9]);
obj.count
// 3
obj.sum
// 16
Not a single return statement to in these examples.
Now look at this .every example.
function isBigEnough(element, index, array) {
return element >= 10;
}
[12, 5, 8, 130, 44].every(isBigEnough);
And finally, from my previous question, I need to add a second return statement like this to avoid the value error.
function isBigEnough(element, index, array) {
return element >= 10;
}
function whenToUseReturn(array) {
return array.every(isBigEnough);
}
whenToUseReturn([12, 5, 8, 130, 44]);
So....... in conclusion, for my original function that started this how am I supposed to exit the loop when I reach false and return it and likewise when all the characters are in the string, how do I return a 'cumulative' true and avoid a Value error. I hope this makes sense and I can clarify with edits to better illustrate my point.
I am returning something so why is it that I have a Value is not what was expected?.
The return statement returns from the callback you pass to forEach, not from isMerge. return statements don't cross function boundaries. isMerge doesn't contain a return statement, hence it returns undefined. If we rewrite the function slightly it might become clearer:
function doSomething(part1, part2) {
return function(character) {
if (part1.includes(character) || part2.includes(character)) {
return true;
} else {
return false;
}
}
}
function isMerge(s, part1, part2) {
splitString = s.split('');
splitString.forEach(doSomething(part1, part2));
}
isMerge('codewars','cdw','oears')
This is equivalent to your code. As you can see, there is no return statement in isMerge.
Not a single return statement to in these examples.
There are no return statements in the forEach examples because forEach doesn't do anything with the return value of the callback, so there is no point in returning anything.
forEach is just a different way to iterate over an array, but it doesn't produce a value like reduce or every.
how am I supposed to exit the loop when I reach false and return it and likewise when all the characters are in the string, how do I return a 'cumulative' true and avoid a Value error.
You cannot exit a forEach "loop". If you have to stop the iteration early, you need to use a normal for (for/in, for/of) loop.
To return and produce a value, you can use your original solution that uses every.
My friend, since you decided to go the "callback way" using .each and the like, you should consider using callbacks, since you cannot return anything in this case. If you do not wish to go the callback way, just use standard javascript, such as:
splitString.forEach(function(character) {
Replace with
for(var i = 0 ; i < splitString.length; i++){
And now you can return. Using "each" to loop an array is just plain unnecessary and prevents you to return.

Checking for collisions using filter()?

Normally I don't have too much trouble figuring out a problem in JS but this time I really need some help understanding this block of code. Mary Rose Cook used this logic in her space invaders game to filter through the bodies array to find collisions with other bodies.
var bodies = [];
...
update: function () {
// bodies is an array of all bodies in the game
var bodies = this.bodies;
var notCollidingWithAnything = function (b1) {
return bodies.filter(function(b2) { return colliding(b1, b2); }).length === 0;
};
this.bodies = this.bodies.filter(notCollidingWithAnything)
// ...insert function to draw the bodies that are in the new bodies array...
}
Can someone please explain how this.bodies.filter(notCollidingWIthAnything) works without passing in any parameters to the argument function? How does the the compiler know to check each element of the array against each other element of the array? Please guide me through what exactly happens in the compiler so that I can understand this.
Can someone please explain how this.bodies.filter(notCollidingWIthAnything) works without passing in any parameters to the argument function? How does the the compiler know to check each element of the array against each other element of the array?
The compiler (well, the JavaScript engine) doesn't know how to call notCollidingWIthAnything with the elements; Array#filter does.
notCollidingWIthAnything is a reference to the function. (Functions are proper objects in JavaScript, so we have references to them just like we have references to other objects.) The code passes that reference into Array#filter, and then Array#filter calls that function once for each element in the array, passing in the element value (and index, and array; it passes three args although we usually only use the first). Then it uses the return value of the callback to decide whether to include the element in the new array it builds.
Here's simplified code for Array#filter so you can see what's going on:
function arrayFilter(callback) {
// Remember this is called with `this` referring to an array-like object
// Create a new, empty array for the result
var result = [];
// Loop through the items
for (var index = 0; index < this.length; ++index) {
// Get the value for this entry
var value = this[index];
// Call the callback
if (callback(value, index, this)) {
// Got a truthy return value, include the value in the result
result.push(value);
}
}
// Return the new array
return result;
}
Again, that's simplified, not perfectly correct; for the perfectly correct steps, see the algorithm in the spec.
Here's an example with logging showing exactly who's doing what:
function arrayFilter(callback) {
console.log("Starting arrayFilter");
var result = [];
for (var index = 0; index < this.length; ++index) {
var value = this[index];
console.log("arrayFilter calling callback with value " + value);
if (callback(value, index, this)) {
console.log("arrayFilter got truthy result, include the value");
result.push(value);
} else {
console.log("arrayFilter got falsy result, don't include the value");
}
}
console.log("arrayFilter done");
return result;
}
function isOdd(value) {
var retval = value % 2 == 1;
console.log("isOdd called with " + value + ", returning " + retval);
return retval;
}
var a = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log("calling `arrayFilter` with `a` as `this`, using `isOdd` callback");
var odds = arrayFilter.call(a, isOdd);
console.log("Resulting array: ", odds);

Categories