COMMUNITY

Preview 5 change to nested function calling


(Aartzrc) #1

I’ve occasionally used a trick to embed a recursive function inside another function (just to keep scope/etc). Here’s a simple (and pointless) example:

class Test {
    static function main() {
        var items = new Array<Int>();
        
        function doRecurse(count:Int) {
            items.push(count);
            if(count > 0)
            	doRecurse(count-1);
        }(5);
        
        trace(items);
    }
}

Kind of like a fold operation, but there can be more complex code/branching within the recursion. The item array pops out the other side with all the data I want without having to pass around extra variables.

This quit working with Preview 5. Not a big deal, but maybe something to check on?

Here’s the sample: http://try-haxe.mrcdk.com/#9AD35
Switch between 4.0.0-preview.1 and any of the dev builds to see the change.

Quick fix looks like this, just a bit messier:

class Test {
    static function main() {
        var items = new Array<Int>();
        
        var doRecurseFunc = function doRecurse(count:Int) {
            items.push(count);
            if(count > 0)
            	doRecurse(count-1);
        };
        doRecurseFunc(5);
        
        trace(items);
    }
}

(Jens Fischer) #2

This doesn’t answer your question, but it seems worth mentioning anyway: you can call named local functions directly, without assigning them to a temp var first:

class Test {
    static function main() {
        var items = new Array<Int>();
        
        function doRecurse(count:Int) {
            items.push(count);
            if(count > 0)
            	doRecurse(count-1);
        }
        doRecurse(5);
        
        trace(items);
    }
}

(Rudy Ges) #3

Another workaround (which do the same thing as @Gama11’s snippet): add brackets around your function declaration:

        (function doRecurse(count:Int) {
            items.push(count);
            if(count > 0)
            	doRecurse(count-1);
        })(5);

Something seem to have changed at expression level, leading h4p5 to consider that function doRecurse(count:Int) { ... } and (5) are two separated instructions, as if separated by a ;.

    var e = macro {
        function doRecurse(count:Int) {
            items.push(count);
            if(count > 0)
            	doRecurse(count-1);
        }(5);
    };
    
    
    var printer = new haxe.macro.Printer();
    trace(printer.printExpr(e));

Outputs:

Macro.hx:16: {
	function doRecurse(count:Int) {
		items.push(count);
		if (count > 0) doRecurse(count - 1);
	};
	(5);
}

It would not have occured to me to be using this syntax, but it’s clearly unexpected behavior. @Simn, what do you think?


(Simon Krajewski) #4

This was a deliberate change to be consistent with other occurrences of }. However, I agree that it looks quite silly in your example, so I’m not sure what to do here…


(Rudy Ges) #5

Could this break somehow at compile time? Like asking for an explicit ; between the function declaration and the “next instruction”.

Edit: what was the change about? Consistency about not needing that particular ; after }? =/