Functions are Functions
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, then 1 = 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()
...
end
or...
function 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.
Arguments
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.
Example of a callback function
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.
Functions and Tables
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
}
or...
t.foobar = function(...)
...
end
or...
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.
Functions are Methods, and Methods are 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().
Please note
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.
Iterators
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.
Conclusion
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.
1 comment
This is a great question. Upvote this, people.