I know from all my studying that a Function
Fires an Event
, But what is the Difference between: Local Function
, and a Regular Function
?
NOTE: The ROBLOX Wiki did NOT Provide an Answer for this.
adark missed the biggest practical different between local
functions and not.
Global variables can be used lexically (in order in source) before they were declared. For instance,
function blah() print( a ) -- where a is a global (not local) variable end a = 5 blah() -- 5
local
variables are only usable after them (lexically -- in source order):
local a = 5 blah() -- nil
The same applies to local
functions -- they can only be used after they are declared, thus the following is invalid:
function blah() print( a() ) end local function a() return 5 end blah() -- a() will cause "attempt to call a nil value"
In addition, it lets you hide functions entirely:
do local function blah(x) return x + math.random() end function save(x) return blah(x) end end print(save(5)) -- 5.432426812304 print(blah(5)) -- attempt to call a nil value
According to Programming in Lua, the following two are equivalent:
local function name() --body end local name; name = function() -- body end
There is no difference between 'local' functions and 'normal' functions, actually.
First, a bit of clarification: Functions do not fire events, they listen to them. The ROBLOX engine itself fires them, passing in relevant information as arguments. Also, Function
is invalid, as Lua is case-sensitive.
What's going on is a shortcut of Lua:
function Name(params) --end end --Is the EXACT SAME as: Name = function(params) --end end
Functions are first-class values in Lua, meaning that you can treat them as any other kind of variable. If you are familiar with C, Lua functions are more accurately function pointers.
This is why you'll see code like this:
loadstring(str)() --Where 'str' is a string of valid Lua code
The first set of parentheses calls loadstring
, which returns a Lua function. The second set of parentheses calls that function.
As you probably know, the local
keyword in Lua indicates the scope of a variable. If not, let me explain:
var1 = true --Global variable. In many implementations, this would be shared across 'Scripts'. Not in ROBLOX, however. local var2 = false --Local variable, to the script. Functionally identical to the above, since the 'scope' is the entire script. Is slightly faster to access. do var3 = "Red Fish" --Global variable. Even though it is declared inside of a code block, it is accessible outside of it. local var4 = "Blue fish" --Local variable. *Not* accessible outside of this code block. print(var1) --> true print(var2) --> false --Variables are always available in "child" blocks, like this one. end print(var3) --> Red Fish print(var4) --> nil --var4 goes out of scope here, so we cannot access it. do local var2 = "Yellow Fish" local var3 = "Pink Fish!!!" --Local variables "override" higher-scoped variables. print(var2) --> Yellow Fish print(var3) --> Pink Fish!!! end print(var2) --> false print(var3) --> Red Fish --Local overrides go out of scope, and the original values are `restored`.
When you make a function local
, the same rules apply. Using top-level local variables in place of globals gives a considerable performance increase after a while, so that's why it's common to see them.
One last word on functions, and Tables as well:
Unlike other variables types, functions and Tables are, effectively, pointers. This is why you get something like this when you try to print
them. When you pass a Table or function around as an argument to some function call, you are actually passing a reference to the Table/function. Any other variable type is copied into a function's 'upvalues', which are the parameters:
local function RunThis(tableParam, functionParam, otherParam) tableParam[27] = true otherParam = otherParam .. "YOLOSWAGGY" print(tableParam) print(functionParam) print(otherParam) end local str = "String" local tab = {"Test1", "Test3"} print(str) --> String print(tab[27]) --> nil print(tab) --> table: XXXXXXXA print(RunThis) --> function: XXXXXXXB RunThis(tab, RunThis, str) --> table: XXXXXXXA, function: XXXXXXXB, StringYOLOSWAGGY -- I use 'RunThis' twice here. The first access is called as a function, indicated by the ()'s, but the second is merely referenced as a Variable. print(str) --> String print(tab[27]) --> true print(tab) --> table: XXXXXXXA print(RunThis) --> function: XXXXXXXB
tab
and RunThis
are pointers, to a Table and a function, respectively. RunThis()
calls the function at the end of the pointer.
Notice, modifying the str
upvalue passed into the RunThis
call does not modify the external str
variable. Modifying the Table's members, however, does modify the external Table. It is not possible (AFAIK) to modify the external function using just its upvalue.
A further note on upvalues: they act as local variables, following the rules above, so:
local tab = {} local tab2 = {} function RunThis(tab, X) tab = {X = 25, Y = 17} X.X = 26 X.Y = 17 X = {} end RunThis(tab, tab2) print(tab.X) --> nil print(tab.Y) --> nil --The `tab` upvalue in the function *overrides* the higher-scoped `tab` declaration on line 1. print(tab2.X) --> 26 print(tab2.Y) --> 17 --The same thing here. Even though we set X to an empty Table at the end of the function, that simply overrode the upvalue.
And, finally, reusing local variables:
In the above code, you'll notice that I did not write local X = {}
. This is because X
is already local. Since it was declared in the function definition as an upvalue (remember, parameters are upvalues), rewriting it in the 'global' scope simply reuses whatever scope the variable already had.
This is because variables in Lua do not have a specified Type. That is,
local x = true x = "false" x = 261
Is all valid Lua. In a language like C, that kind of code would produce a compile error, as x
is either a Boolean or a String or an Integer, and definitely not all three at once.
All three of those x
declarations are local
, because the initial declaration is. When a higher-scoped variable is overridden, the most recent scope is used:
local x = 27 function RunThis() x = 45 --Same var as on line 1. If this code were all wrapped in a code block, this would not be accessible outside of it. local x = 18 --New scope, to this function. x = "BOOLEAN" --Same scope as the line above, *not* the same as Line 1. end RunThis()
If you've been paying attention thus far, you'll realize that you can declare functions inside of code blocks:
function makeFunction(str) local function func() print("yolo" .. str) end return func end makeFunction("swag")() --> yoloswag
And as members of Tables:
local tab = {} tab.Func = function() --code end --Or: function tab.Func2() --code end
This second case is how you can make methods
as opposed to functions:
tab = {Applesauce = true} function tab.func(t) print(t.Applesauce) end function tab:func2(appl) --Note the `:` here. self.Applesauce = appl --"Method declaration" gives you a `self` parameter. end --This function is identical to: function tab.func2(self, appl) self.Applesauce = appl end --You can call these as either functions *or* methods: tab.func1(tab) --> true tab.func2(tab, "Hooligans!") --Although we edit the Table passed to the function, and not `tab`, this works because only the Table *reference* is sent, not a copy of the Table. tab:func1() --> "Hooligans!" tab:func2(true) --And, finally, you can actually use *other* tables in these functions calls: local tab2 = {} tab.func2(tab2, "Peanuts") tab.func1(tab2) --> Peanuts
Local functions are more optimized, and should be used where possible.
Locked by woodengop and adark
This question has been locked to preserve its current state and prevent spam and unwanted comments and answers.
Why was this question closed?