Hi everyone. So I have been looking at different codes written by different people and I am seeing different types of functions. I know the normal function is written as either
function func (...) --Do Stuff end;
or
local function func (...) --Do Stuff end;
Yes. I do know the differences between the above functions. But the functions following, I do not understand the point of it? Is it completely user preference? Is there a situation where I would use one over other?? If you could explain it to me, it would be very helpful.
Type 1 I do not see a point of this. I mean, isn't the above functions also assigning a value to a variable? Why is this function explicitly assigning a value to variable?
Variable = function(...) --Do Stuff end;
Type 2 Isn't this just an alternative to the first function?
Variable.Event:Connect(function(...) --Do Stuff end);
Type 3 Why should i bother using this function when I can call a function later on?
spawn(function(...) --Do Stuff end);
Type 4 I get this function's point but this person wrote delay(0)
is what i dont get.
delay(0, function(...) --Do Stuff end;
Type 5 Whaaat?
_G.Variable = function(...) --Do Stuff end;
Type 6 Whhaat??
for v in function(...) --Do Stuff end do; end;
Type 7 Whatttt?
Variable = { func = function(...) --Do Stuff end; }; Variable.func();
Type 8 What even the point of writing like this. And what is method?
Variable = {} function Variable:method(...) -- Do Stuff. end
These are the types I found. From Type #5, i do not understand any of them. The roblox wiki makes no sense to me. Should I even bother knowing all of these? I mean, can't I just stick to one type of function? Why bother knowing all of these function?
Thank you so much for taking your time reading this.
There are no different types of functions in Lua. Functions are their own data type just like how numbers
, booleans
, tables
, and so on, are also their own data types. Most of the examples you've provided differ in how functions are being used, rather than what types they are. Those particular examples would be analogous to saying...
if
x = 1
is a variable assignment, then1 = x
is a different type of variable assignment.
In both cases, the variable is x
and there is no distinction between them other than what order they're in. In programming, order matters for syntactical reasons. In pure logic and mathematics, there is no difference between x = 1
and 1 = x
, just like there's no difference in programming between...
x = function() -- variable is x ... end
function x() -- variable is x ... end
Despite there being no difference, you should still stick to using one over the other unless a specific circumstance suggests otherwise. Consistency plays an important role in maintaining clean code.
Your examples two-through-four are the same, in that they all demonstrate how functions can be passed as arguments to another function. The specific act of passing function A as an argument to function B and having function B call function A, is known as a callback. Again, this is not a type of function, but rather a name that describes how the function is being used.
function beta(f) f('data') end function alpha(...) print('from callback:', ...) end beta(alpha)
from callback: data
Passing function alpha
to function beta
results in function beta
calling function alpha
, passing an argument to function alpha
in the process. Callbacks typically pass arguments back to the functions they receive, however they're not required to do so in order to still be considered a callback.
Your fifth and seventh examples are also the same. In Lua, _G
is a global variable that points to a table of other global variables stored in the script environment. _G
is just a table. As alluded to before, there's no difference between the following...
local t = { foobar = function(...) ... end }
t.foobar = function(...) ... end
function t.foobar(...) ... end
There are side-effects to declaring a function as a new index to a table rather than declaring the function inside the table, which may or may not be favorable in specific circumstances. For example, if you stored two functions inside a table and you wanted a reference to both functions from the code in their bodies, declaring the function as a new index would allow you to do this...
local t = {} t.alpha = function() print('run first') end t.beta = function() t.alpha() print('run second') end
You could, of course, do this just as well...
local t = {} local function alpha() print('run first') end local function beta() alpha() print('run second') end t.alpha = alpha t.beta = beta
However, we reach the same conclusion; these are not different types of functions, just different ways of declaring and allocating functions.
Your eighth sample is probably the most diverse out of the rest, because it actually has a very distinct purpose. Methods are an Object-Oriented Programming (OOP) concept that allow you to call a function on an object as if you were commanding that object to behave a certain way. Calling a method on an object means the same thing as calling a function with the first argument being the object. You can see how this works for yourself in the ROBLOX environment using various different methods inherited from the instance class. For example...
part:Destroy() part.Destroy(part)
Both variations of calling the function Destroy
from above are exactly the same. The colon symbol used to call a method is just syntactic sugar; meaning it's purely for the programmer's convenience. Here's an example of how methods in Lua allow for this to happen...
local profile = {} profile.firstName = "John" profile.lastName = "Doe" function profile:getName() return self.firstName .. " " .. self.lastName end print(profile:getName())
John Doe
The example above illustrates use of the self
variable for methods called using a colon :
, however, methods can also be called on an object traditionally...
print(profile.getName(profile))
John Doe
Again, the code above yields the same as profile:getName()
.
This barely scratches the surface of OOP. This doesn't cover anything about classes, inheritance, etc. I strongly recommend doing research on OOP yourself if you're interested.
Your sixth example illustrates a function used as an iterator. Iterators typically tell generic for loops how to traverse a data structure. The use of pairs
is a classic example of an iterator, because internally, the pairs
function is just this...
function pairs(t) return next, t end
This is also why you can skip the call to pairs
in a generic for loop, and just supplement it for next, t
which often people do. This adds a negligible difference to performance, but some people use it as preference.
This was a lengthy answer, but it certainly didn't cover any of these subjects in the detail they deserve. I strongly recommend reviewing some tutorials on OOP concepts, and functions in general. I'll try and edit this answer a bit to insert links to sources that you may find useful in proper contexts. Hope this helped clear things up for you, let me know if you have any questions.
Overview
Right so before I explain all of those examples I'd like to make one thing clear. Functions are simply just a type of value. In Lua they're actually objects (so are tables, userdata and threads), meaning that when you assign to or pass an object as an argument, you're manipulating a reference to that value. There are no "different types of function".
1
foo = function() end
Is simply another way to define a global function, it's analogous with this function definition:
function foo() end
The function expression itself is the value, you're simply assigning it to your variable foo. Also note that you should be defining local functions, since they're lexically scoped (can only be referenced in the current scope or block) and local variables are inherently slightly more performant. It's good practice to use local variables.
2
The Roblox API provides you with RBXScriptSignals/Event Signals or simply "events". These are fired whenever a specific event occurs. You can subscribe to, or more commonly listen to events with listener/callback functions. You can connect an event to any function you'd like, but this function will be invoked in a seperate thread, and will take the parameters defined in the event's description on the Roblox wiki.
local function bar() end Instance.Event:Connect(bar)
Note that a function that takes another function as one of its parameters is called a "higher order function"
3
spawn(foo)
schedules the callback function passed to be called in a separate thread, so it'll essentially run in a separate 'environment' so to speak.
4
spawn(foo)
is analogous to delay(0, foo)
, since neither yield (or wait) before calling the function.
5
In a Roblox environment, _G
is a reference to a table that's shared across all scripts on the machine. tab.foo
is the same as tab["foo"]
and allows you to index a table quicker, assuming that the key is a valid identifier (a legal variable name). .
notation is a form of syntactic sugar which is a syntax feature in Lua that makes our lives easier.
6
A generic for loop takes an iterator function that returns the next value in the table when its called in each iteration. It pretty much defines how the for loop should traverse the table. Here's the PiL article on generic for.
7
All values in Lua are first class entities, meaning that they support all operations usually available for every other entity (passed as an argument, returned from a function and assigned to a variable). Since function values are first class, they can also be stored in tables, just like any other value. Remember that .
allows you to index a table with a valid identifier, say we have something like this:
local tab = { foo = function() return "bar" end }
You can index the table tab
for the function foo
like so:
tab.foo()
tab["foo"]()
Both are valid and do exactly the same thing.
8
A method or member function is a function that act on their respective object and are defined in a class definition. I wont go into OOP since that's a completely different topic, but you can read this article for more information. :
implicitly passes an object as its first argument, and is another type of syntactic sugar. Here's an example:
workspace:GetChildren()
workspace.GetChildren(workspace)
These are both exactly the same.
I hope you understood this answer, if you have any questions just post a comment.
ScriptGuider answers this question quite well, but I figured I'd cover a few more specifics that weren't really covered in ScriptGuider's answer.
Variadic arguments and returns are represented using ...
- This is a special symbol in Lua, known as varargs
. It represents a tuple of values, and expands into the values it represents as though they were simply inserted raw.
As such:
function varargs(...) -- ... print(...) end varargs("one", 2) -- print("one", 2)
Any values inserted into the ...
parameter as arguments are expanded wherever they're used. This isn't strictly true, but it's the easiest thing I can think of.
When you write
local function funcName(...) end
It expands as
local funcName funcName = function(...) end
Which means that funcName
is available as an upvalue inside of the new function body.
When you use a for ... in ... do
-style loop, the real format of it is
for nextArg, ... in iteratorFunction[, iteratorConstant[, initialArg]] do
And all missing optional inputs become nil. At the start of the iteration, it calls iteratorFunction(iteratorConstant, initialArg)
, with the returns becoming variables for the loop. Every further iteration it calls iteratorFunction(iteratorConstant, nextArg)
until nextArg
is nil
function table:Method(...) end
is just the same as
function table.Method(self, ...) end
and
table.Method = function(self, ...) end
Type 1 is basically how you prefer to declare a function
You can do
local function a() --stuff end
But you can also do
local a = function() --stuff end
since functions are variables.
Type 2 is connecting to an event. That function will get called each time the event is fired. Different events fire when certain things happen, i.e. when a part is touched, when a player joins, etc.
A function which has no name, but rather is used only once in a function, like the one in this "type", is called an anonymous function
Type 3 is the same as type 2, except the function is inside spawn()
, which makes it run cooperatively, meaning you can i.e. run multiple while loops at the same time.
Type 4 is basically because they probably wanted to put the code into a separate scope, and didn't want to use do end
. It's equal to the following example:
(function(...) --stuff end)(args);
Type 5 is setting a variable of the global _G
table to the function, probably so it can be used accross scripts.
Type 6 is using a custom iterator function inside a for loop. Just like you use pairs()
, you can use your own function aswell
Type 7 is declaring a function as the value of a key in a table.
Type 8 is the same except it's called with :
. Here it's most likely used because of their preference, but in most cases the :
is used to take advantage of the self
argument, for example in Object Oriented Programming (when you create classes or such)
Locked by Zafirua, Amiaa16, User#21908, LifeInDevelopment, and Axceed_Xlr
This question has been locked to preserve its current state and prevent spam and unwanted comments and answers.
Why was this question closed?