4

I'm attempting to gradually refactor existing code. I have a set of functions that are defined, and only differ by one of the internal arguments:

function loadGame1():void
{
    loadGame("save1");
}
function loadGame2():void
{
    loadGame("save2");
}
function loadGame3():void
{
    loadGame("save3");
}
//... snip many, many lines

// Note- I cannot pass function arguments at this time!
picker(loadGame1, loadGame2, loadGame3 ...);    

I'm trying to refactor at least part of this (I can't completely replace the whole thing yet, too many interdependencies).

Basically, I want to be able to generate a big set of functions with the difference between the functions being a internal parameter:

var fNames:Array = new Array("save1", "save2", "save3");
var funcs:Array = new Array();
for (var i = 0; i < fNames.length; i += 1)
{
    trace("Creating function with indice = ", i);
    funcs.push(
        function() : void 
        {
            saveGame(fNames[i]);
        }
    )
}

picker(funcs[0], funcs[1], funcs[2] ...);

However, as I understand it, closure is causing the state of i to be maintained beyond the scope of the for loop, and any attempt to call any of the generated functions is failing with an out-of-bounds error, which is what you would expect given that i will reach fNames.size + 1 before i < fNames.size evaluates to false.

So, basically, given that I need to generate functions that are passed as arguments to a pre-existing function that I cannot change currently. How can I dynamically generate these functions?

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
Fake Name
  • 5,556
  • 5
  • 44
  • 66

1 Answers1

4

Try to use IIFE:

for (var i = 0; i < fNames.length; i += 1)
{
    (function(i){
        trace("Creating function with indice = ", i);
        funcs.push(
            function() : void 
            {
                saveGame(fNames[i]);
            }
        )
    })(i);
}
Ivan Chernykh
  • 41,617
  • 13
  • 134
  • 146
  • +1. Also it may be good idea to make it into separate function and name appropriately - [Curry](http://stackoverflow.com/questions/36314/what-is-currying), [Currying](http://en.wikipedia.org/wiki/Currying). Here is also [ActionScript Curry](http://stackoverflow.com/questions/359635/flex-implementing-classic-curry-function-in-actionscript) question. – Alexei Levenkov Nov 02 '13 at 06:14
  • Yep, this nailed it. I wish there was a way to have finer grained control of variable scoping, though (and a way to copy by value!), but that's just me not really being used to actionscript. – Fake Name Nov 02 '13 at 06:15
  • @FakeName at least nice that in all ecmascript-based language this feature exist, for example i'm using it in javascript too – Ivan Chernykh Nov 02 '13 at 06:29