Androider
Androider

Reputation: 21335

Declaring Lua Functions and referencing with correct name

What is the difference between the following Lua scripts in terms of function scope. How would it effect the need to require 'calculator' in some other Lua script. And how would it be referenced in say a LuaState.getGlobal(function_name). What would be its proper function name? Also any comment on advantages/disadvantages of the declaration approaches.

A) Calculator.lua

function foo(n) 
   return n+1;
end

B) Calculator.lua

calc= {}
function calc.foo(n) 
  return n+1;
end

C) Calculator.lua

function foo(n) 
   return n+1;
end
function calculator()
   calc = {}
   calc.foo=foo
   return calc
end

Upvotes: 3

Views: 308

Answers (2)

Michal Kottman
Michal Kottman

Reputation: 16763

Not exactly an answer, but a comment on semantics - in Lua, you do not declare a function, you create it. The function becomes available at the time the function(...) ... end is executed. How it is available depends on where you store it.

You have to remember that:

function myfun(foo) print('foo') end

is just syntactic sugar for:

myfun = function(foo) print('foo') end

If you do not do anything special, myfun becomes a global variable stored in the global state (accessible through _G). If you say local myfun before actually calling function myfun() end, the function (actually a closure) will be stored in the local variable and available only to the scope of the local variable.

If you use require, it just finds the file and loads it once. It doesn't do anything fancy with the module like hiding globals, etc. So if you write function foo() end in your module Calculator.lua, then calling require 'Calculator' will create a function in global foo, which you can access using LuaState.getGlobal("foo"). If you create a table of functions (step B), you have to use 2 steps:

L.getGlobal("calc")   -- pushes the "calc" global (a table) to the stack
L.getField(-1, "foo") -- gets the "foo" field from the table 

Upvotes: 2

Nicol Bolas
Nicol Bolas

Reputation: 474436

I don't know what it is you mean exactly by the "scope" of these scripts. Exactly what these scripts do depends on how they're being executed. You could give them a different environment, thus changing what they think of as "globals".

So, I will explain what each of these scripts does based on the assumption that you are loading them with dofile, dostring, or something of the like. That is, you're applying them to the global environment.

A)

This creates a single global variable, foo, which is a function.

B)

This creates a single global variable, calc, which is a table. This table has a single entry, with the key foo, who's value is a function.

C)

This creates two global variables. foo is a function. calculator is also a function. Each call to calculator will cause the global variable calc to be overwritten. The new value of calc will be a table that has a single entry, with the key foo, who's value is a copy of what is stored in the global variable foo.

It's hard to say what the "advantages" of method C are, since it makes no sense. It creates two functions instead of one, and that second function keeps creating new tables.

B is just a "namespace" scoped version of A. The general expectation with Lua modules is that including them will usually create some table that will contain all of the functions in that module, to avoid name conflicts with existing global state. In that regard, B may be better. But it depends mostly on what this script will be used for.

Personally, for simple shell scripts and utility scripts, I don't bother with proper module scoping. When I do make a proper module, I generally use the module Lua function.

Upvotes: 2

Related Questions