[Basic Question] Differences between ":" and "."

Hello, I am not really a new dev, I relearned the lua recently (I was on nodejs), but there is something I don’t really understand.

What is the difference between : and .

local lol = "Wanna do a brickbattle ?"
if lol:match('Brick') then
    ...
end
local lol = "Wanna do a brickbattle ?"
if lol.match('Brick') then
    ...
end

Thank you !

The second option will raise an error. Colon is used in objective oriented programming when it comes to methods. When colon (“:”) is used, table that calls chosen method will automatically get passed as a parameter. The following two methods to find a match return the exact same result:

local sentence = "Who doesn't like brick battle?"
if sentence:match('brick') then
	print("Match found!")
end
local sentence = "Who doesn't like brick battle?"
if string.match(sentence, "brick") then
	print("Match found!")
end
4 Likes

a:b(c) is syntax sugar (a nicer way to write something) for a.b(a, c). Since strings have a metatable whose __index field points to string, you’re just passing the string you are calling it on as first argument. Without the . it would be like doing string.match, where you have to pass the target string anyway.

4 Likes

“:” passes self (which is a variable that points to the object it was called from) while “.” does not

for example:

local myTable = { name = "table" }

function myTable:getName()
   -- the colon passes "self" which would direct itself to the table because that's what it was called from
   return self.name
end

function myTable.getName()
    -- since a dot was passed, "self" does not exist
    return self.name -- would error
end

this is also the same as:

local myTable = { name = "table" }

myTable.getName = function(self)
   -- in this example, you would pass "self" yourself as the first parameter
   return self.name
end

myTable.getName = function()
    -- "self" does not exist because we did not define it
    return self.name -- would error
end

print(myTable:getName()) -- prints "table"
print(myTable.getName()) -- would error

basically what @sjr04 said

2 Likes

Since strings have a metatable whose __index field points to string

I don’t really understand this sentence.

1 Like

I’m not really going to go too in-depth about metatables, but I’ll give a quick explanation anyway.

Metatables let you extend the functionality of something, usually a table. One of the many metamethods is __index, which is invoked whenever you try accessing something that doesn’t exist.

Since strings don’t have the actual methods attached to them, each time you try indexing the string with : or ., the __index metamethod is invoked and looks for the method in the string library.

image

So this poorly drawn diagram attempts to show how it is indexing the string table with the upper key (which points to the string.upper function) and calling it with the string "hi"

2 Likes

Thank you ! Now i understand better.

1 Like

Is “a” placed at a random argument or only the first one?

No, the first one. a:b(c) implicitly passes a as first argument, or like @HugeCoolboy2007 mentioned, self.

@Dominus_Marceau these are metatables in a nutshell.

You will hear the sentence “metatables are very powerful” very often. That’s because they are always useful. When you start to work with OOP and data, tables are very common and so are their helpful sidekicks, metatables. You can think of them as tables that include special functions to change behaviour of the table they are appended to. They hold configurations for that table and let you add functionality to it. There is a big number of so called metamethods, about which you can read here (amazing post by @starmaq).

Let’s look at an example:

--[[
	Welcome to the RENT A BloxyCAR! This is an automated
	machine, helping you complete your holiday!
	
	We have four cars you can rent here:
]]
local cars = {"BloxAudi", "RoPorsche", "BloxFord", "Rotsubishi"}

--[[
		-- "This is absolutely nice, but I'd like to
		   drive a RBX_BMW. In fact, I love it! Is there
		   any way I could rent it here?" --
	
	Unfortunately, that's not possible, as we don't
	have any RBX_BMW's for rent. Lucky for you, we have
	a metatable implemented!
	
	[!][!] Special deal ahead [!][!]
	
	RANDOM CHOICE:
					get a ROTOYOTA or a FERRORI !
]]

local cars = setmetatable(cars, { 
	__index = function(table, key)
		-- match is equal to true if both random numbers match
		local match = math.random(1, 10) == math.random(1, 10)
		return match and "Ferrori" or "RoToyota"
	end
})

-- If the element is not part of the table,
-- prepared key is returned instead of nil.
print(cars.RBX_BMW)

__index may look confusing at first, but is actually not scary and is one of many useful metamethods.

@sjr04 and @HugeCoolboy2007 really took time to write nice posts explaining this further.

Now back to your case. Why does this work…

if sentence:match('brick') then end

…and why doesn’t the following (?):

if sentence.match('brick') then end

Because, as stated before, when colon is used, a table that called the method, which is in our case :match, is automatically past as an argument, a parameter to that function. When dot is used, parameter has to be manually entered, which means that is former example, string.match method has no string to try to find word “brick” in.

This would work:

local sentence = "Who doesn't like brick battle?"
if sentence.match(sentence, 'brick') then
	print("Match found!")
end

But it seems pointless to call a method with a table and then manually pass it as argument again. That’s why we write string.match() instead. String functions are all part of the same standard lua string library.

3 Likes