Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return a value from a Javascript function without using "return"

Tags:

javascript

In JavaScript, is there any mechanism that would make it possible to set a function return value without using the keyword "return"?

like image 949
Agamemnus Avatar asked Dec 27 '13 06:12

Agamemnus


People also ask

How can I return a value without return?

If no return statement appears in a function definition, control automatically returns to the calling function after the last statement of the called function is executed. In this case, the return value of the called function is undefined.

What can I use instead of return in JavaScript?

To put it simply a continuation is a function which is used in place of a return statement. More formally: A continuation is a function which is called by another function. The last thing the other function does is call the continuation.

What does a JavaScript function return if no return is given?

If no return value is specified, JavaScript will return undefined . In many languages the result of the last statement is returned (more useful, IMO). These are called implicit returns.


2 Answers

Of course you can. All the other answers talk about:

  1. Assigning a value to a variable in a parent scope.
  2. Assigning a value to a property of an object in a parent scope.

There is however a third method and this method is very powerful: CONTINUATIONS.

For a moment let's assume that return is a function. For example:

function add(a, b) {
    return(a + b);
}

Now what if you didn't want to use return? We could do something like this:

function add(a, b, ret) {
    ret(a);
}

To put it simply a continuation is a function which is used in place of a return statement. More formally:

A continuation is a function which is called by another function. The last thing the other function does is call the continuation. It doesn't do anything else after that.

Hence a continuation is like the functional equivalent of the return statement.

Continuations have a lot of advantages:

  1. You can pass multiple return values to the continuation.
  2. You can write functions recursively instead of iteratively.
  3. You can choose not to call the continuation (in which case you're changing the control flow).
  4. You can choose to call one of multiple continuations (like a throw continuation).

However continuations have two main disadvantages:

  1. If you write programs in continuation passing style then you'll end up with a lot of nested functions.
  2. JavaScript doesn't have tail call elimination. Hence recursive functions increase the stack size.

For example:

function fib(n, k) {
    switch (n) {
    case 0:  k(0); break;
    case 1:  k(1); break;
    default:
        fib(n - 1, function (x) {
            fib(n - 2, function (y) {
                k(x + y);
            });
        });
    }
}

fib(20, console.log); // maximum recursion depth exceeded

You can use setTimeout to eliminate tail call recursion:

Function.prototype.async = function () {
    return setTimeout.bind(null, this, 0).apply(null, arguments);
};

function fib(n, k) {
    switch (n) {
    case 0:  k(0); break;
    case 1:  k(1); break;
    default:
        fib.async(n - 1, function (x) {
            fib.async(n - 2, function (y) {
                k(x + y);
            });
        });
    }
}

fib(20, console.log); // 6765

You can use backcalls from LiveScript to make your code look better:

Function::async = -> setTimeout.bind(null, @, 0) ...

fib = (n, k) -->
    | n == 0    => k 0
    | n == 1    => k 1
    | otherwise =>
        x <- fib.async n - 1
        y <- fib.async n - 2
        k x + y

fib 20, alert # 6765

You can try it out for yourself on the http://livescript.net/ site. Just use a value smaller than 20. Preferably 10.

like image 100
Aadit M Shah Avatar answered Nov 14 '22 23:11

Aadit M Shah


There is no other way to return a value, that's what return is for. But since we have side effects, you can edit a variable in a wider scope like this:

var a = 5;
function setA(x)
{
    a = x;
}
setA(6);

Alternatively you can pass an object to the function and by using pass by reference change variables in that object. This page details how that works.

As mentioned above, this is not the same as a result value, as the following will fail:

var newA = setA(a); // undefined instead of 5
like image 28
fredrik Avatar answered Nov 14 '22 21:11

fredrik