Forward declaration help

So I thought I was getting to really understand variable scoping and the use of forward declarations to prevent problems when, for example, a function is defined somewhere after it is called.

However, I tried to setup a button that calls a function positioned right after its definition (but with forward declaration) and it didn’t work. Moving the function above the button declaration works. But can someone explain why the forward declaration of the function doesn’t work in this case? Here’s my sample code:

I should add that this code occurs within a createScene function.

    local startGame

    

    local startBtn = widget.newButton{

        defaultFile = “images/goBtn.png”,

        overFile = “images/goBtn_over.png”,

        width = 60,

        height = 60,

        left = 30,

        top = 120,

        onEvent = startGame

    }

    

    function startGame(e)

        

        if ( e.phase == “ended” ) then

            print(“start clicked”)

            storyboard.gotoScene( “game”, “crossFade”, 10 )

        end    

        return true

    end

    

Hi jeff15,

This is a somewhat common confusion in forward-declaring functions in Lua. You have the right idea, but the syntax needs to be just a little different:

Instead of this:

[lua]

local startGame

function startGame( e )

end

[/lua]

Try this:

[lua]

local startGame

startGame = function( e )

end

[/lua]

Hope this helps,

Brent Sorrentino

In lua you can assign to variable everything you want as number, string, table, timer and functions (in reality what is passed is address in memory where object is stored - but it’s only if you are interested :slight_smile: )

So first you created variable and next you created function with the same name - the result was 2 objects with different positions in memory and what’s more, because the same name was used, function has hidden the variable.

As suggested above, you first create variable and somewhere further you must assign assign function to it.

Ah, thanks to both of you! Makes sense. I see now that I was creating a variable but by the way I wrote the code, I wasn’t assigning the function to it, but was creating a function with the same name. 

Many thanks!

Jeff

Hi jeff15,

This is a somewhat common confusion in forward-declaring functions in Lua. You have the right idea, but the syntax needs to be just a little different:

Instead of this:

[lua]

local startGame

function startGame( e )

end

[/lua]

Try this:

[lua]

local startGame

startGame = function( e )

end

[/lua]

Hope this helps,

Brent Sorrentino

In lua you can assign to variable everything you want as number, string, table, timer and functions (in reality what is passed is address in memory where object is stored - but it’s only if you are interested :slight_smile: )

So first you created variable and next you created function with the same name - the result was 2 objects with different positions in memory and what’s more, because the same name was used, function has hidden the variable.

As suggested above, you first create variable and somewhere further you must assign assign function to it.

Ah, thanks to both of you! Makes sense. I see now that I was creating a variable but by the way I wrote the code, I wasn’t assigning the function to it, but was creating a function with the same name. 

Many thanks!

Jeff

Hi, I tried the following and got assertion failed if the function is below the addEventListener…

local buttonFunction

btn1 = display.newRect( 50, 50, 40, 40 );
btn1:addEventListener (“tap”, buttonFunction )

buttonFunction = function ( event )
    print (“btnClick!”)
end

For the

This is because, when you declare the local “placeholder” for buttonFunction, it’s not a function or really anything that can have an event listener added to it. Is there some reason why you can’t just put the function above the “btn1” object?

Brent

Hi Brent, Sure that I can put the function above object “btn1”, just wondering what is happening with forward reference.

Like piotrz55 previously mentioned, using forward reference, there are two addresses allocated in memory, which is the variable, and then the function, both are in different addresses. is it somehow they have any linkage between them?

local btn1
btn1 = display.newRect( 50, 50, 40, 40 )

First line, local btn1 allocated an address in memory for the local variable btn1;

The second line, the display object is assigned to the variable btn1, is that the address is memory the same as the first one created in “local btn1”? Or a new address is allocated to the second btn1, so “local btn1” and “btn1” are in different addresses and two different entity?

display.newRect will create a new object in a different address, so behind the scene, three “objects” has been created? local btn1, btn1, display.newRect?

If we write without forward reference:

local btn2 = display.newRect( 50, 50, 40, 40 )

It will allocated two memory addresses instead of three?

This is a good question.  

Why does something like this work? 

local rect, reset local function draw() rect = display.newRect( display.contentCenterX, display.contentCenterY, 200, 200) rect:addEventListener( "tap", reset ) end reset = function() display.remove(rect) rect = nil draw() end draw()

Hi @mort,

I assume you mean:

[lua]

rect:addEventListener( “tap”, reset )

[/lua]

and not :

[lua]

rect1:addEventListener( “tap”, reset )

[/lua]

I don’t see any other citation of “rect1” in your code.


Anyway (for @jvmaster77 too), the reason @mort’s code works is because, when you just create an empty reference, it doesn’t contain any “methods” in regards to Corona. So, you can’t add an event listener to it (because it’s essentially nothing at that point). However, when you assign a display object to this variable, internally you also provide it with a series of object-appropriate methods and properties that Corona can use, i.e. the ability to assign an event listener, among other things.

Does that explain it better?

Brent

@Brent: Thanks, that was a typo.

However, I think we’re both more concerned with why adding an event listener with a forward-declared listener function doesn’t work. (I apologize for not making it clearer before, by saying I was talking about the referenced function, and not referenced display object.)

Like so:

local reset local rect = display.newRect( display.contentCenterX, display.contentCenterY, 200, 200) rect:addEventListener( "tap", reset ) reset = function() display.remove(rect) rect = nil end

vs. my previous example, whereby it somehow works when an addEventListener is called within an enclosing function (i.e. draw).

There is a huge difference between this form…

local someFunction local function otherFunction(x) return someFunction(x + 1) end someFunction = function(x) return x+1 end print(otherFunction(0)) -- this'll work, prints 2

…which uses only “native Lua” calling “native Lua” and will defer the evaluation of “someFunction” within “otherFunction” until actually called, so everything works as expected…

…and THIS form (as per jvmaster77)…

local someListener someDisplayObject:addEventListener("whatever", someListener) someListener = function(event) -- will never be called end

…which attempts to pass a reference to a not-yet-existent function to an internal API routine, so the API gets a nil when expecting a function, so no event is ever gonna fire that function, as the API has no way to know what function you intended to provide itwith (or even if you ever got around to actually defining it AT ALL!)

That is, addEventListener() isn’t passed the “name” of the function to lookup later, it’s passed a reference – but it’s a nil reference to something that doesn’t exist yet, there is no memory address allocated for a function by simply writing “local someListener”. By the time you actually DO define the function and allocate storage for it in the next line, it’s too late, the API will never know about it.

It’s a bit like trying to create a closure around a forward declaration - the two concepts are mutually at odds with each other: you either need the reference as it exists NOW… or not, and instead wish to access whatever that variable references at some time in the future. Sending references to the API is like the closure scenario – it’s gonna pass the value as it exists *right now*.

fwiw, hth

@davebollinger, @Brent: Great explanations, thanks! Together they are two very nice perspectives/unique ways of explaining the issue.

However, why does something like this work (when adding a referenced listener function)?

In other words, why does wrapping “rect:addEventListener…” in a function make any difference?

EDIT: I think I see the difference.

Regardless of the initial ordering of the functions, and even if the lower (reset) function is referenced above the upper one (add), I still have to CALL the upper function (add) after the lower one (when involving an API call, that is)?

local reset local rect = display.newRect( display.contentCenterX, display.contentCenterY, 200, 200) local function add() rect:addEventListener( "tap", reset ) end reset = function() display.remove(rect) rect = nil print("tapped") end add()

It all boils down to “when does it actually happen?” (retrieving the value of the variable, that is)

In your example, nothing actually happens until you call add() at the very end. Inside the execution of add(), Lua will scan up through environment scope to find/retrieve the value of a variable named “reset” (the “closest” of which currently happens to contain a function - yeah!) and push that value (a reference to the function) as a parameter to the addEventListener() call, so all is well.

hth

@dave

Thanks! 

So, by calling add() after the actual reset function, I’m essentially letting the variable reference know that the reset function exists (since add() has the actual reset function in scope!)

“add()” sees “reset = function()”; allows “local reset” (the reference) to know location of “reset = function()”; the listener can now call “reset = function()” through the reference. 

Hi, I tried the following and got assertion failed if the function is below the addEventListener…

local buttonFunction

btn1 = display.newRect( 50, 50, 40, 40 );
btn1:addEventListener (“tap”, buttonFunction )

buttonFunction = function ( event )
    print (“btnClick!”)
end

For the

This is because, when you declare the local “placeholder” for buttonFunction, it’s not a function or really anything that can have an event listener added to it. Is there some reason why you can’t just put the function above the “btn1” object?

Brent

Hi Brent, Sure that I can put the function above object “btn1”, just wondering what is happening with forward reference.

Like piotrz55 previously mentioned, using forward reference, there are two addresses allocated in memory, which is the variable, and then the function, both are in different addresses. is it somehow they have any linkage between them?

local btn1
btn1 = display.newRect( 50, 50, 40, 40 )

First line, local btn1 allocated an address in memory for the local variable btn1;

The second line, the display object is assigned to the variable btn1, is that the address is memory the same as the first one created in “local btn1”? Or a new address is allocated to the second btn1, so “local btn1” and “btn1” are in different addresses and two different entity?

display.newRect will create a new object in a different address, so behind the scene, three “objects” has been created? local btn1, btn1, display.newRect?

If we write without forward reference:

local btn2 = display.newRect( 50, 50, 40, 40 )

It will allocated two memory addresses instead of three?