Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lua: How to call a function prior to it being defined?

Tags:

lua

What is the syntax to create the function, but then add it's implementation further down in code?

So roughly like this:

  • Define function doX
  • Call doX (further down in the code)
  • doX implemention (i.e. all functions down at the bottom of the file)
like image 588
Greg Avatar asked Sep 05 '12 23:09

Greg


3 Answers

You only need to have a variable to reference. local funcName is sufficient for your purposes with one caveat. This will work:

local funcName
function callIt()
  print(funcName())
end
function defineIt()
  funcName = function() return "My Function" end
end
defineIt()
callIt()

As long as you define it (defineIt) before you call it (callIt), it should work as expected. You can't do something like this though (and this is the caveat):

local funcName
print(funcName())
funcName = function() return "My Function" end

You will get an error: attempt to call local 'funcName' (a nil value).

like image 71
Paul Kulchenko Avatar answered Sep 17 '22 14:09

Paul Kulchenko


oh...so there's really no way to call funcName prior to having actually defined the function then? i.e. you still need to make sure defineIt is called before your first call to funcName itself?

I wanted to clarify this point, and I felt that an answer would be the better way than a comment.

Lua is a much simpler language than C or C++. It is built on some simple foundations, with some syntactic sugar to make parts of it easier to swallow.

There is no such thing as a "function definition" in Lua. Functions are first-class objects. They are values in Lua, just like the number 28 or the string literal "foo" are values. A "function definition" simply sets a value (namely, the function) into a variable. Variables can contain any kind of value, including a function value.

All a "function call" is is taking the value from a variable and attempting to call it. If that value is a function, then the function gets called with the given parameters. If that value is not a function (or a table/userdata with a __call metamethod), then you get a runtime error.

You can no more call a function that hasn't been set in a variable yet than you can do this:

local number = nil
local addition = number + 5
number = 20

And expect addition to have 25 in it. That's not going to happen. And thus, for the same reason, you can't do this:

local func = nil
func(50)
func = function() ... end

As Paul pointed out, you can call a function from within another function you define. But you cannot execute the function that calls it until you've filled in that variable with what it needs to contain.

like image 20
Nicol Bolas Avatar answered Sep 17 '22 14:09

Nicol Bolas


As others have written, you cannot call a function at runtime that has not been assigned prior to the call. You have to understand that:

function myFunc() print('Something') end

Is just a syntax sugar for this:

myFunc = function() print('Something') end

Now, it makes sense that this kind of code would not work the way you want it to:

print(greeter(io.read())) -- attempt to call global 'greeter' (a nil value)
function greeter(name) return 'Hello '..name end

When you use the greeter variable, its value is nil, because its value is set only on the next line.

But if you want to have your "main" program on the top and the functions at the bottom, there is simple way to achieve this: create a "main" function and call it as the last thing on the bottom. By the time the function is called, all the functions will be set to the corresponding global variables:

-- start of program, your main code at the top of source code
function main()
    local name = readName()
    local message = greeter(name)
    print(message)
end

-- define the functions below main, but main is not called yet,
-- so there will be no errors
function readName() io.write('Your name? '); return io.read() end
function greeter(name) return 'Hello, ' .. name end

-- call main here, all the functions have been assigned,
-- so this will run without any problems
main()
like image 37
Michal Kottman Avatar answered Sep 21 '22 14:09

Michal Kottman