Principle behind short func syntax

What is the principle behind this?
newArr.some(Array.isArray) === newArr.some(elem => Array.isArray(elem))

How is posible that they are parsed as equal?
I thought that newArr.some(Array.isArray) === newArr.some(Array.isArray()) (assuming that some is a loop and that JS assumed each val as the implicit arg of the func), but it’s not. So, I’m confused. Please, help me.

function flatMultiArr(arr) {
let newArr = [];
 newArr = arr.reduce((acc, curr)=>{
   return acc.concat(curr)
   }, []);
return newArr.some(Array.isArray)
? flatMultiArr(newArr)
: newArr
}

flatMultiArr([1, {}, [3, [[4]]]]);//[ 1, {}, 3, 4 ]
function flatMultiArr(arr) {
let newArr = [];
 newArr = arr.reduce((acc, curr)=>{
   return acc.concat(curr)
   }, []);
return newArr.some(elem => Array.isArray(elem))
? flatMultiArr(newArr)
: newArr
}

flatMultiArr([1, {}, [3, [[4]]]]);//[ 1, {}, 3, 4 ]
1 Like

Consider these three examples.

[[]].some(Array.isArray) //= true

[[]].some(function(element) {
  return Array.isArray(element)
}) //=true

[[]].some(isArray) //=true

function isArray(element) {
  return Array.isArray(element)

}

Array.isArray is a function.

In the first example, the each element of the array is implicitly passed to the function Array.isArray. If that returns true for any of the elements, the condition is met. The some function continues until a match is found and returns true when it is. The second example is more explicit but it does the same thing and the third clarified it in my head.

The first example is doing what the third one does, just uses less characters.

Jan, Hi!
First 2 propositions are fine; however, they don’t respond the answer. The forth proposition meaning, depends on what elem is. Finally, I disagree with the last one, cause (despite the intention would be aligned with the first 2 examples) it actually produces a reference error isArray is not defined, and as far as I can see is not a valid extent of [[]].some(Array.isArray).

According with my last research, this has to do with the lamda calculus principle eta

function isArray(element) {
  return Array.isArray(element)
}
[[]].some(isArray) //=true


The final example works, you just need to use all the code. I’ve put the related function above it this time.

The equality between the two has nothing to do with lambdas or calculus as far as I’m aware.

Hi @leoncpaulo, this is a very good question. If I understand correctly, what you’re asking is, what is the difference between:

newArr.some(Array.isArray)

versus

newArr.some(Array.isArray());

You’re asking “Why are they different?” Am I understanding that correctly?

If yes, then I’ll try to explain what’s going. To make things clear, let’s write our own version of Array.prototype.some():

function some(predicate, arr) {
    for (let item of arr) {
        if (predicate(item)) {
            return true;
        }
    }
    return false;
}

We have our own version of some() which takes a function (called predicate) and an array (arr). We run through the array, and call predicate() on each item. If predicate() returns true, then return true. If we get through the whole array with no matches, we return false. So, we could use it like so:

const isObject = (item) => {
    return (typeof item === 'object');
}

const mixedArr = [{}, 1, 'hello', {foo: 'bar'}];
const strings = ['123', 'abc'];

const mixedHasObjects = some(isObject, mixedArr); // true
const stringsHasObjects = some(isObject, strings); // false

Here we create a function and assign it to a variable (isObject). Then we take that function variable and pass it to some() along with the array. And we get back true or false.

Now, Array.isArray is a function, just like isObject. And like isObject, we could assign it to a variable if we want:

const myIsArray = Array.isArray;

// We can now use myIsArray with some()
const nestedArray = [[], []];
const flatArray = [1, 2, 3];
const nestedArrayIsNested = some(myIsArray, nestedArray); // true
const flatArrayIsNested = some(myIsArray, flatArray); // false

But if we tried doing the following, it wouldn’t work:

const myIsArray = Array.isArray();
// myIsArray isn't a function now, it's false
// Calling Array.isArray() is the same as calling Array.isArray(undefined)
// So this doesn't work:
const nestedArray = [[], []];
const nestedArrayIsNested = some(myIsArray, nestedArray); // Error

And this is the same as calling:

const nestedArray = [[], []];
const nestedArrayIsNested = some(Array.isArray(), nestedArray); // Error

But if we pass Array.isArray without the brackets, we’re passing a function, not the result of calling the function.

I hope that all makes sense so far. If so, then all of the following things are all equivalent:

myIsArray                     // We assigned Array.isArray to myIsArray earlier
Array.isArray                 // This is the built-in function Array.isArray
(elem) => Array.isArray(elem) // This is a function that takes a parameter and does nothing but
                              // call Array.isArray with it

So, if we take that one step further, all these are all doing the same thing:

newArr.some(myIsArray)                     // Call .some() with our myIsArray function
newArr.some(Array.isArray)                 // Call .some() with Array.isArray
newArr.some((elem) => Array.isArray(elem)) // Call .some() with a function that does nothing
                                           // but call  Array.isArray

I hope that clears things up. In case you’re wondering, there’s a name for this stuff. It’s called “higher-order functions”. If you’re interested in finding out more about this, I’ve written a longer article about it on my blog: What are higher-order functions, and why should anyone care?.

1 Like