Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Javascript, what's better than try/catch for exiting an outer scope?

Tags:

javascript

In Javascript, I sometimes want to return a value from a scope that isn't the current function. It might be a block of code within the function, or it might be an enclosing function as in the following example, which uses a local function to recursively search for something. As soon as it finds a solution, the search is done and the outer function should just exit. Unfortunately, I can't think of a simpler way to do this than by hacking try/catch for the purpose:

function solve(searchSpace) {
    var search = function (stuff) {
        var solution = isItSolved(stuff);
        if (solution) {
            throw solution;
        } else {
            search(narrowThisWay(stuff));
            search(narrowThatWay(stuff));
        };
    };
    try {
        return search(searchSpace);
    } catch (solution) {
        return solution;
    };
};

I realize one could assign the solution to a local variable and then check it before making another recursive call, but my question is specifically about transfer of control. Is there a better way than the above? Perhaps involving label/break?

Edit: since the answers to date are variations of "ew that's bad you're not supposed to do that", let me add some necessary context. I'm hacking on an open-source compiler that targets Javascript. No one is going to write this code by hand, so please don't tell me "this is a bad programming technique". What I want is a better code generation technique. The question is whether anyone has any clever hack for exploiting Javascript to get more flexible control transfer.

The reason assigning the result to a local variable and checking it is ruled out is because that requires understanding the code in a way that is hard for a compiler to do.

like image 682
gruseom Avatar asked Apr 09 '10 17:04

gruseom


2 Answers

It seems I stand corrected on the intent of the question. If statements are are a useful and readable way to structure code and make it flow however you want to. There's a reason goto was taken out of so many languages, because you don't need it. And it seems like, based on your example code, you're using a try-catch block as a form of goto. If you don't want certain things to run then use if statements or equivalents:

function solve(searchSpace) {
    function search = function (stuff) {
        //|| will only return the first value if that value is truthy, subsequent values will be ignored
        return isItSolved(stuff) || (search(narrowThisWay(stuff)) || search(narrowThatWay(stuff)));
    };
    return search(searchSpace);
};

I know of no way to break out of function calls like you want. You can break out of loops using labels, but it doesn't seem that's much help to your situation. Other than that, I don't think JavaScript has any such ability beyond your use of exceptions

like image 83
Bob Avatar answered Sep 23 '22 02:09

Bob


function solve(stuff) {
    return isItSolved(stuff) || solve(narrowThisWay(stuff)) ||     solve(narrowThatWay(stuff));
}

Bob's way is good... exept that he uses twice the function statement (and that he uses ; after a function delaration without an assignment)... and that as we can do it that way, function solve actually is function search.

PS : This code will epically fail if the isItSolved, narrowThisWay or narrowThatWay functions can return a value evaluated to false as a positive result. In this cas, you would have to use ? : statement in order to check if all responses are !== undefined.

PS2: And of ourse, if these function can send an error, you have to catch it...

like image 21
xavierm02 Avatar answered Sep 23 '22 02:09

xavierm02