Posted on by

This tutorial discusses the basics behind anonymous functions and closures in Lua. Let’s begin by inspecting how a typical Lua function looks:

local function myFunction( someParameters )
   --function content
end

Under the hood, this creates a variable called myFunction that is scoped locally to this code block and is stored where the code block exists in memory. For instance if you did…

print( myFunction )

…the Terminal/console would print something like this:

0x4a8cd834

This is the location in memory where Lua will jump when the function is called.

Lua also permits you to define a function like this:

local myFunction = function( someParameters )
   --function content
end

In this notation, it’s more clear that you’re assigning a variable to a code block (or more specifically the memory address of that code block). In the end, both notations accomplish the same thing, but the second notation allows some additional flexibility. When written in this form, you are effectively taking an unnamed block of code and giving it a name.

Lua permits you to write these functions and use them without a name.  This is called an anonymous function.

Anonymous Functions

To explore anonymous functions, let’s look at some examples :

timer.performWithDelay( 1000, myFunction, 10 )

In this case, the timer.performWithDelay() function takes a time interval in milliseconds, a function to execute, and an integer count to repeat. Thus, myFunction() will fire 10 times on every 1000 millisecond interval, but what’s really happening is that Lua is passing the memory address of the function to the timer.performWithDelay() function. This means that you could also write…

timer.performWithDelay( 1000,
      function()
         print( "Hello World" )
      end,
   10 )

…or this (note the semicolon after the print() command…

timer.performWithDelay( 1000, function() print( "Hello World" ); end, 10 )

In both cases, instead of using a variable to hold the function’s memory address, you simply create an unnamed anonymous function that will execute when the timer fires. Anonymous functions can be used anywhere you need to code an onComplete or callback listener function, for example in transition.to(), audio.play(), etc., but how often should you use them? From the perspective of code readability and sustainability, perhaps not very often — they tend to make your code harder to read, but if the function will only be used in that specific scope of your code, and it’s relatively short, anonymous functions are a valid coding technique.

In the second example, notice the semicolon at the end of line 3. If you write just one statement of code, for example one print() statement, the semicolon isn’t required, but if you write multiple statements on one line, they must be separated by semicolons. Therefore, it’s a good habit to include the semicolon, even if you just include one line of code within the anonymous function.

Be cautious: there are times when you can not use anonymous functions. One specific instance is when you assign functions to event listeners. Because the event listener system in Corona is based around storing the address of functions that are specified to handle events, the address that you pass in when removing an event listener via object:removeEventListener() must match the address that was passed in to object:addEventListener().

Lua Closures

Lua closures are another useful technique. Where they truly shine is in passing parameters to function handlers that are not looking for extra parameters. To illustrate this, let’s look at a transition.to() example:

transition.to( playerObject, { time=1000, alpha=0, onComplete=myFunction } )

In this example,  myFunction() will be passed a single parameter, target, which is the object that is transitioning. But let’s assume that the display object is a member of on array and you need to know more about the object itself in the function that gets called. This can be accomplished via a Lua closure:

local balls = {}
balls[1].ball = display.newImageRect( "greenball.png", 64, 64 )
balls[1].color = "green"
balls[2].ball = display.newImageRect( "redball.png", 64, 64 )
balls[2].color = "red"

for i = 1,#balls do
   transition.to( balls[i].ball,
      { time=250, x=200,
         onComplete=function( target )
            myFunction( target, balls[i].color );
         end
      }
   )
end

In this example, instead of calling myFunction() as part of the callback, you call an anonymous function instead. That anonymous function takes the received target parameter that transition.to() provides and, inside it, you call your named function, passing along the target object reference and the color property of the ball.

Closures are more than just anonymous functions. When you have a function inside of a function, the child function has access to all of its parent’s local objects, or upvalues. Normally, when a function ends, any locally-scoped variables go out of scope, so when you call the function again, you begin anew. Consider this example:

local function counter()
   local i = 0
   while i < 10 do
      i = i + 1
   end
   return i
end
print( counter() )

Each time that you call counter(), it will print the value of 10 because when the function's scope ends, so do its local variables.

Now let's modify the function to actually return a function that does the counting:

local function counter()
   local i = 0
   return function ()
      i = i + 1
      return i
   end
end
local counter1 = counter()

At this point, we have a new function in our counter1 variable, and when we run it multiple times…

print( counter1() ) --result: 1
print( counter1() ) --result: 2

…Lua realizes that the anonymous function may still get used and that it should hold on to the current value of i in its current scope. This is what a Lua closure does for you.

To expand on this concept, if you were to create another counter, the following results would occur:

local counter2 = counter()
print( counter1() ) --result: 3
print( counter2() ) --result: 1
print( counter1() ) --result: 4
print( counter2() ) --result: 2

Essentially, each version of the anonymous function holds its own i and keeps it scoped within itself. So, when you create a second counter, i resets to 0 for that instance.

In Summary

As you can see, anonymous functions and closures provide a powerful way to keep track of variable instances on a per-function basis. In the context of Corona SDK, this allows you to pass parameters to functions in which you normally don't control the passed-in content.

To continue your exploration of these topics, please continue to the Lua documentation site.


Posted by . Thanks for reading...

10 Responses to “Tutorial: Anonymous Functions and Closures”

  1. RichieLoco

    This really helps thanks! Closures (and other more advanced concepts) are covered in the “Corona SDK Hotshot” book, however, whilst being intuitive the book doesn’t explain too well these concepts – this has certainly filled a gap in my knowledge.

    Cheers
    Rich

    Reply
  2. William Bell

    Regarding to memory usage , the function will be retained in memory only if I assigned this to a variable right ?

    Example:
    print ( counter 1 ( ) ); — result: 1
    print ( counter 2 ( ) ); — result: 1
    print ( counter 3 ( ) ); — result: 1
    memory usage : three function instances retained

    If calling the function directly, then can I assume:
    print ( counter ( ) ); — result 1
    print ( counter ( ) ); — result 1
    print ( counter ( ) ); — result 1
    memory usage : zero function instance retained

    Thanks for the tutorial writeup !

    Reply
  3. Luis Herranz

    Thanks for the tutorial, good work.

    I’ve always wondered if there’s an elegant way to do this Javascript technique in Lua:
    var counter = function() {
    var i = 0;
    return function() {
    i = i + 1;
    return i;
    }
    }();
    In this JS code you are creating and executing the parent function at the same time, so the final counter function is the one inside (with the upvalue i in its scope).

    Reply
    • Star Crunch

      It’s easy enough. You just need some parentheses to get the grammar right.

      Then:

      local counter = (function()
      local i = 0
      return function()
      i = i + 1
      return i
      end
      end)()
      print(counter()) — 1
      print(counter()) — 2

      Reply

Leave a Reply

  • (Will Not Be Published)