Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
16

What does all these different types of functions do? [closed]

Asked by 5 years ago
Edited 5 years ago

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.

0
This is a great question. Upvote this, people. jackfrost178 242 — 5y

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?

4 answers

Log in to vote
10
Answered by 5 years ago
Edited 5 years ago

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() -- variable is x
    ...
end

or...

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.

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.

0
gg, 4 minutes before i posted my answer lol LifeInDevelopment 364 — 5y
Ad
Log in to vote
5
Answered by 5 years ago
Edited 5 years ago

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.

Log in to vote
4
Answered by 5 years ago
Edited 5 years ago

Extension to ScriptGuider's Answer

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

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.

"local function" Format

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.

Generic Iterators

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

Method Declaration Sugar

function table:Method(...) end

is just the same as

function table.Method(self, ...) end

and

table.Method = function(self, ...) end
Log in to vote
1
Answered by
Amiaa16 3227 Moderation Voter Community Moderator
5 years ago

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)

0
All functions are anonymous in Lua. Avigant 2374 — 5y
2
Wrong. If the function has an identifier, it's not anonymous. RayCurse 1518 — 5y
0
^ Amiaa16 3227 — 5y
0
Functions aren't variables, they don't have identifiers. Technically all function expressions are anonymous, but you often refer to a function that isn't assigned to a variable as "anonymous". LifeInDevelopment 364 — 5y