Home > Blockchain >  two function with same functionality return different value because i haven't use "return&
two function with same functionality return different value because i haven't use "return&

Time:07-22

I wrote a function that flatten and array.


  const multiArray = [1, [2, 3, [4, [5]]], 6, [7, 8, 9, [10]]]

  let newArray = []
  const flatenArray = (params) => {
    params.map((sm) => {
      if(Array.isArray(sm)) {
        return flatenArray(sm)
      }
      newArray.push(sm);
    })
    return newArray
  }

  //console.log(flatenArray(multiArray)) result [1,2,3,4,5,6,7,8,9,10]

The above function works fine.

but if I remove the return keyword from the "if" block then does it returns something else?

let newArray2 = []
  const flatenArray2 = (params) => {
    params.map((sm) => {
      if(Array.isArray(sm)) {
        flatenArray(sm)
      }
      newArray2.push(sm);
    })
    return newArray2
  }

  console.log(flatenArray2(multiArray)) 
  //result [1,[2,3,[4,[5]]],6,[7,8,9,[10]]]

Now I would like to know...

Why should I use the return keyword there even when I'm calling it?

What is happening when I use the return keyword there?

CodePudding user response:

What is happening when I use the return keyword there?

The function (the callback that you're passing to map) does return a value and stop executing. This means it will not reach the next line, newArray.push(sm);, after the if statement, which does push the sm array onto the result array in your second implementation.

Why should I use the return keyword there even when I'm calling it?

You shouldn't actually. Using an else statement would be much cleaner (and also you shouldn't abuse map):

const flattenArray = (params) => {
  for (const sm of params) {
    if (Array.isArray(sm)) {
      flattenArray(sm)
    } else {
      newArray.push(sm);
    }
  }
  return newArray
}

CodePudding user response:

Every function has to "return" something, and that's result value of your function!

Imagine a sum function without a return value!

const noreturn_sum = (a, b) => {
  a   b
}

if you don't return something, your function returns undefined implicitly.

so if you gonna print the result of noreturn_sum, you will get:

console.log(noreturn_sum(1, 2))

>> undefined

This is true even in your example, let me explain : (may I cleanup your code a little bit?)


let newArray2 = []

const flatenArray2 = (params) => {
  // PART 1 ---------
  params.map((sm) => {
    if(Array.isArray(sm)) {
      flatenArray(sm) // PART 1.map.fn ---------
    }
    newArray2.push(sm);
  })
  // END PART 1 ---------

  // PART 2 ---------
  return newArray2
  // END PART 2 ---------
}

console.log(flatenArray2(multiArray)) 

A. your function for each parameter does this:

  1. checks if it's an array:

true => call the function again to reach to a non-array value

false [it's a value] => add it to newArray2

  1. then returns undefined

B. then your whole params.map(... returns an array of undefined, because your function inside map (that I explained it in (1.) and (2.) returns undefined

C. you return newArray2 at the end of the function.

note that your flatenArray2 function always return the newArray2 but inside "PART 1.map.fn" you "discard" it (or you "ignore" it in other words)

but in the last experssion console.log(flatenArray2(multiArray)) you gave the returned value to the console.log function.

CodePudding user response:

When you do not use the result, either by assigning, passing or returning, you are solely relying on the side effects on the function.

Eg. in your flatenArray if you pass it a [[1]] sm will be [1], thus the if test is true and it will recurse with [1]. It will then fail on the test because 1 is not an array and push 1 to newArray. It then returns newArray which is then instantly returned and no more of that function is used in that round. You never use the resulting array from map since you are never ever returning this so one could question why you didn't use forEach instead to enforce that it is just for side effects (mutating newArray). If you were to remove return it will continue down and do newArray.push(sm) even though it is an array Thus you would get both flattened results and unflattened results in the result array mixed and doubled up. This could be prevented by having the last statement in an else so that the function either did the array thing or the element thing.

The flatenArray2 doesn't recurse as it uses flatenArray that populates newArray and not newArray2 so it will only make a shallow copy of the original array due to the flattened elements being added to newArray and the unflattened elements being added to newArray2 which is the only result that is returned.

If you were to call any function twice you will get the results of the previous runs in the second.

This is how I would have made it to prevent it from keeping results from previous rounds and actually using the results returned:

const multiArray = [1, [2, 3, [4, [5]]], 6, [7, 8, 9, [10]]];

const flattenPure = (arr) => {
  const helper = (acc, e) => 
    Array.isArray(e) 
    ? e.reduce(helper, acc) // reduce the array e with acc as accumulator
    : [...acc, e];          // make a new array with elements from acc and the element e
    
  return arr.reduce(helper, []); // start with an empty accumulator
}

console.log("Once Pure", flattenPure(multiArray));
console.log("Twice Pure", flattenPure(multiArray));

Using Array.proptype.push makes a faster version, however then why not just use Array.prototype.flatten)?

const multiArray = [1, [2, 3, [4, [5]]], 6, [7, 8, 9, [10]]];

const flattenSide = (arr) => {
    let res = []; // this is new every time flatten is called
    const helper = (e) => {
        if (Array.isArray(e)) {
            e.forEach(helper); // indirect recurse for each element
        } else {
            res.push(e);
        }
        // hidden return undefined here
    };
    helper(arr); // flatten arr with result in res
    return res;  // return result
}

console.log("Once Side", flattenSide(multiArray));
console.log("Twice Side", flattenSide(multiArray));

  • Related