Should I use : or . when calling a ModuleScript function?

Hello! I have a rather simple question that I cannot find an answer for.

Basically, I’ve noticed that using “:” exhibits different behavior than using “.” when calling a ModuleScript function - E.G Module.PrintHello() works differenty from Module:PrintHello() but I can’t figure out what differences there are.

When would I use either one and what are they for?

Cheers :slight_smile:

1 Like

Suppose you have a table with a function in it:

local t = {}

function t.myfunc(foo)
    doSomething(foo)
end

You can call this function with . easily:

t.myfunc(2) --> arguments: foo = 2

If, in that function, you wanted to change other things in the table, you might add the table as the first argument, so you can refer to it in the function (a common pattern in OOP Lua):

t.thing = 2

function t.myfunc(self, foo)
    self.thing = self.thing + foo
end

Now, you would pass in t as the first argument:

t.myfunc(t, 2) --> arguments: self = t, foo = 2

Calling a function with : makes this whole idea easier by silently inserting that first table argument for you:

t:myfunc(2) --> arguments: self = t, foo = 2

There’s also matching syntax for declaring functions in a table that let you exclude the first parameter from the function declaration:

function t:myfunc(foo)
    self.thing = self.thing + foo --> self is actually the first argument, and foo the second
end

Hope that helps :slightly_smiling_face:

7 Likes

Well if you were to let’s say you have a function that is supposed to change the color of a brick maybe, and you have 2 formats for this function, the one with : and the one with ..
So let’s say we wanna use one of these functions on a part.
Technically you’ll do something like this.

module.ChangeColor(Part, "Really Red") -- you can do it like this or
Part:ChangeColor("Really Red") --or like this

Can you notice the difference?
With the .ChangedColor() one we have to put which part we want to change the color to in the paramaters while the :ChangeColor() applies to the part directly without having to put it in the paramaters, and that is really the main difference.
I hope you get it.

And this difference actually makes more sense if you think about it this way, let’s say you were making these function inside of your module script.

-- dot formot
function module.ChangeColor(object, color)
   object.BrickColor = BrickColor.new(color)
end

-- double dot format
function Part:ChangeColor(color)
   self.BrickColo =BrickColor.new(color)
end

self is pretty much the object that we are using the function on.
if I were to part:("Really Red") the self here is part itself. And in here you can say that self in here module.ChangeColor(part, "Really Red") is also part.

But same different, the self in the dot function is inside of the paramaters while in the double dot function it’s no inside the paramaters but it’s the part that we are directly using the function on without having to put inside of the paramaters

1 Like

If you are returning a table from a module script, you use .. If you are returning a table from a constructor from a module script, you use :. All other practices I see are frankly unfounded and get confusing.

Tables of functions vs objects is something you could also look into to differentiate better.

So it’s a bit like applying a custom function to an object? If I understand you correctly

This is very descriptive and helpful, thanks! I’ll try applying these in new code.

1 Like

This example doesn’t work at all. You can’t apply custom methods to objects without wrapping them first.

If a custom object was implied then it would’ve made more sense to use that, but the code makes it seem like you want it to work on normal part Instances.

1 Like

Well it’s not really custom, it’s just doing littearly the same thing, but with the part that we are applying to in different places.
Also consider what @Autterfly said

1 Like

Yeah I know I rushed a bit, just wanted to explain self in general and the difference between the two types

Just to be sure I understand this concept correctly, gonna write an example.

Outside Script:

h:sayHello(2)

Module:

h = {
[1] = "Hello1", 
[2] = "Hello2", 
[3] = "Hello3"}

function h:sayHello(num)
      return(self.num) -- Should return Hello2
end

end

Would this example return Hello2?

Would test in studio but I’m working on things at the moment so asking here.

Small correction: self.num should be self[num], but other than that, looks good!

2 Likes

Using the : method is also basic OOP, so if you’re using that approach in a game or you’re working on something using it, it’s good practice for organization.

1 Like

Yeah, this has some strong connection with OOP, which stands for object-oriented programming.
You can find some info here and here.

2 Likes

Whereas using . you may need to declare self as your initial parameter using : Lua will add an extra hidden parameter. Basically OOP. Here is a link to the Lua documentation.

1 Like