Search code examples
recursionhaxemutual-recursion

how to write mutually recursive functions in Haxe


I am trying to write a simple mutually recursive function in Haxe 3, but couldn't get the code to compile because whichever one of the mutual functions that appears first will report that the other functions in the group is undefined. A minimal example is below, in which mutually defined functions odd and even are used to determine parity.

static public function test(n:Int):Bool  {
    var a:Int;
    if (n >= 0) a = n; else a = -n;

    function even(x:Int):Bool {
        if (x == 0)
            return true;
        else
            return odd(x - 1);
    }
    function odd(x:Int):Bool {
        if (x == 0)
            return false;
        else
            return even(x - 1);
    }
    return even(a);
}

Trying to compile it to neko gives:

../test.hx:715: characters 11-14 : Unknown identifier : odd
Uncaught exception - load.c(181) : Module not found : main.n

I tried to give a forward declaration of odd before even as one would do in c/c++, but it seems to be illegal in haxe3. How can one define mutually-recursive functions like above? Is it possible at all?

Note: I wanted to have both odd and even to be local functions wrapped in the globally visible function test.

Thanks,


Solution

  • Rather than using the function myFn() {} syntax for a local variable, you can use the myFn = function() {} syntax. Then you are able to declare the function type signiatures before you use them.

    Your code should now look like:

    static public function test(n:Int):Bool  {
        var a:Int;
        if (n >= 0) a = n; else a = -n;
    
        var even:Int->Bool = null;
        var odd = null; // Leave out the type signiature, still works.
        even = function (x:Int):Bool {
            if (x == 0)
                return true;
            else
                return odd(x - 1);
        }
        odd = function (x:Int):Bool {
            if (x == 0)
                return false;
            else
                return even(x - 1);
        }
        return even(a);
    }
    

    This works because Haxe just needs to know that even and odd exist, and are set to something (even if it's null) before they are used. We know that we'll set both of them to callable functions before they are actually called.

    See on try haxe: http://try.haxe.org/#E79D4