skip to Main Content

I have a function that returns either false or a number other than 0. Now I’m calling this function in another function to conditionally return the number.

function falseOrNumber() { ... }

function otherFunction() {
    // ...
    if (falseOrNumber()) return falseOrNumber()
    // ...
}

Now I was wondering, if there is an elegant way to perform this in one line without calling falseOrNumber() twice.

So I’m not looking for the obvious solution:

let i = falseOrNumber()
if (i) return i

This is nothing game changing, but I’ve encountered similar situations several times in the past and I’d like to know if there is a cleaner way.

3

Answers


  1. If you assign the return value of the function to a variable inside the if statement, you can re-use it with the return statement:

    function falseOrNumber() { ... }
    
    function otherFunction() {
        // ...
        let result;
        if(result = falseOrNumber()) return result;
        // ...
    }

    If you want more elegance, there is probably a way to have one return statement for the entire function, instead of returning early. You can also use a comma expression to turn multiple expressions into a one-liner.

    function otherFunction() {
        return falseOrNumber() || (other, code, here);
    }

    Update: your comment says that you have multiple functions like falseOrNumber. If so, you can do this:

    function otherFunction() {
      return falseOrNumber() || somethingElse() || orSomethingElse();
    }
    Login or Signup to reply.
  2. You mentioned that your use case is to call this many times over and over in the same otherFunction.

    If you are trying to test several numbers in sequence, you can do it like so:

    function otherFunction() {
        return falseOrNumber(1)
            || falseOrNumber(2)
            || falseOrNumber(3)
            || falseOrNumber(4)
            || falseOrNumber(5)
            || falseOrNumber(6)
            || falseOrNumber(7)
            || falseOrNumber(8)
            || falseOrNumber(9);
    }

    If you need to do this in a loop, you can share one variable:

    function otherFunction() {
        let t = false;
        for (let i = 0; i < 100; i++)
            if (t = falseOrNumber(i))
                break;
        return t;
    }
    Login or Signup to reply.
  3. If your usecase is as what @maraaaaaaaa said, in the future you might be able to do something like this if this proposal gets accepted:

    function otherFunction() {
      const testcases = [/* ... */]; // An extremely expensive array
      return testcases.values().map(falseOrNumber).find(Boolean);
    }
    

    testcases.values() returns an iterator which goes over all elements, one by one. .map() map those with a function (in this case, falseOrNumber) on the fly, yet returns another iterator and .find(Boolean) returns the first mapped element which is not falsy.

    Unlike testcases.map(), testcases.values().map() is lazy: it only evaluate as needed. This is also the case when it comes to both Array#find() and Iterator#find() (there’s no docs for this just yet, only this).

    Try it (this doesn’t work yet):

    console.config({ maximize: true });
    
    const testcases = [1, 2, 3, 4];
    
    console.log(
      testcases.values()
        .map(e => e ** 2)
        .find(e => e % 9 === 0)
    );
    <script src="https://gh-canon.github.io/stack-snippet-console/console.min.js"></script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search