The dot and colon operator

Hello,

I have some confusion about the dot and colon operators in Corona. I’ve seen the tutorial that differentiates bw them when they are called as functions.

My confusion is in regards to the libraries and built-in functions. For example:

object:setFillColor(1,0,1)

object.Text = (“text”)

Why is setFillColor called with a colon and why are many others called with dot operator? (display.newRect, object.xScale etc etc)

Thanks

The simple answer is this:

  • Calling with a dot simply calls that function on it’s own.
  • Calling with a colon passes the variable to the left of the colon as the first parameter in the function.

For example, let’s create an object (always a table, in Lua) and also create a function…

local t = {} local function doAthing( paramA, paramB ) print( paramA, paramB ) end

We can make the function a property of the table object, like this…

t.doAthing = doAthing 

or like this (if we didn’t write it earlier)…

function t:doAthing( paramA, paramB ) print( paramA, paramB ) end

or even like this…

local t = { doAthing = function( paramA, paramB ) print( paramA, paramB ) end } 

Now, if we look at the first version of that function, we can call it on it’s own, like this:

doAthing( "one thing", "another thing" )

Both of the parameters that we pass in get received inside the function as their named values.

But, once we’ve declared the function as a property of a table, we can call it “on the table”, like this…

t.doAthing( "one thing", "another thing" )

That is exactly the same as the previous call - both parameters are received exactly the same way.

We can also call it with the colon, which basically tells the function about the object which it is “being called on”, like this…

t:doAthing( "one thing", "another thing" )

The only difference here is that the two parameters, paramA and paramB, will be the table ‘t’ and the string “one thing” - “another thing” will get lost.

So, why is this useful?

Because you can write a function which doesn’t know anything about it’s parent object but still reference that parent object. Here’s what I mean…

Let’s say I want a function which will print a string property called “.class” of whatever table it is assigned to. I could create a bunch of tables all with different .class values…

local a = { class="first" } local b = { class="bee" } local c = { class="the sea" }

I could also create a function with the standard first parameter called ‘self’ and use that to get the table which the function has been assigned to (it doesn’t matter what that parameter is called, but ‘self’ is a convention.)…

local function printMyClass( self ) print( "My parent's class is: "..self.class ) end

I could then assign that function to all of those tables…

a.printMyClass = printMyClass b.printMyClass = printMyClass c.printMyClass = printMyClass

I can even create another one with the same class assigned to it but in a more creative way…

local d = { class = "I got a D :(" classPrinter = printMyClass }

So now, if I were to call all of those table’s printMyClass() functions they would print their parent’s .class property out - bear in mind that I effectively use a different name for the last one…

a:printMyClass() d:printMyClass() c:printMyClass() d:classPrinter()

And this would output…

first bee the sea I got a D :(

see horacebury’s reply, then… the “why” of the difference is because of two things:

  1.  things like .xScale are properties not methods , so you’d never call them with a colon, instead you access them with a period

  2.  methods on corona classes  (like display, audio, physics, etc) are called with a period, because there’s only ever one of them, so they have no need for a “self” parameter to distinguish “who” the method was called on.  otoh, methods on returned individual  instances (like rects, images, etc) are called with a colon, because they do need a “self” parameter to tell “who” the method was called on

hth

I got confused as well when I started corona.

I understand basically you only use the : if it is an object mothod.

So 

object:method()

object.property

class.property

class.mthod()

Not sure if I am 100% right

Yes, you are.

The short version of what I wrote earlier is that if you want a function as just a function on it’s own, you make it available to your code by calling it with a . on a table. This is like providing the table as a library object (like the math. namespace) and the function as just a function (e.g.: round() ) - Conversely, if you want a function on an object to do something for that object, you assign it to the object and call it with : (This gives you the benefit of being able to reuse functions by using ‘self’ or not, if you don’t want to.)

The responses were very helpful. Thank you guys.

@horacebury

In your second example (printMyClass) you’ve called the functions using the dot operator rather than the colon, but the function uses self so it will return the error: attempt to index local ‘self’ (a nil value)

It should be:

a:printMyClass() b:printMyClass() c:printMyClass() d:classPrinter()

Corrected, above.

Sheesh, you guys make everything so complicated!!! And, what’s worse: some things said above are plain wrong!

It can be summed up much, much simpler:

Using the : or colon operator is exactly the same as using a dot operator, but with an extra parameter “self” as the first parameter in the function.

So, yes, these two are exactly the same expressions:

object:eatFruit(“banana”)

object.eatFruit(self, “banana”)

Or in the same vein, these two expressions are also the same:

object:setFillColor(0,1,1)

object.setFillColor(self, 0,1,1)

You can actually freely interchange the colon with self argument, and the dot without the self argument.

That’s basically all there is to it.

Regarding method and property: the dot is used for both, so the poster saying that dot was for properties, not methods, was wrong.

Small addition: the colon is only used for methods (or functions, if you prefer that terminology).

Another small addition: the “self” parameter is very useful when you start using object oriented programming, or pseudo-OOP, as it is sometimes referred to in Lua / Corona. The self parameter, as said above, refers to the object on the left of the line of code - this is the object that is calling the function.

For absolute clarity, the code below looks like “calling” the function, not “defining” the function. When calling the function, self isn’t defined, the object is so:

object.eatFruit(self, "banana")

should be:

object.eatFruit(object, "banana")

Inside the code for eatFruit, the first parameter is called “self”. So when defining the function:

function object.eatFruit( self, fruit ) function object:eatFruit( fruit )      print( self, fruit ) end

Both function definitions are identical and you access “self” within the function.

Rob

Very true, Rob.

If I may give a tip: I always use the DOT notation when writing my own code. While for pros it doesn’t matter that much, I think for beginners to intermediate coders it helps to see what is being passed as parameters, and where it is passed.

opinions will legitimately differ on this, but…  the colon is just sugar, but then so is the dot.  a “purist” might even argue that the form t"f" would thus be the preferred way to word t.f(t) or t:f() because then the internal behavior is fully revealed by the syntax.  (i myself would rather use the sugar)

Hi Dave,

Very much a matter of preference of course, so there is no right or wrong way. I did and still do like, however, the fact that all passed arguments are “visible” when I read my code, hence the dot notation for me personally.

Also, since all my code is modular, my code will always read like the contents of a table:

myClass.aCertainFunction = function(self, argument1, argument2) -- doSomethingHere end

Thanks for the very informative responses guys.

You’re welcome. In case you’re venturing down that path, I found Lua’s flavour of object oriented programming to be very easy and intuitive to use and learn with the exception of a few small things. Once you’ve gotten past these simple obstacles (with the help of the forum) it’ll help your code reach a higher level in no time!

The simple answer is this:

  • Calling with a dot simply calls that function on it’s own.
  • Calling with a colon passes the variable to the left of the colon as the first parameter in the function.

For example, let’s create an object (always a table, in Lua) and also create a function…

local t = {} local function doAthing( paramA, paramB ) print( paramA, paramB ) end

We can make the function a property of the table object, like this…

t.doAthing = doAthing 

or like this (if we didn’t write it earlier)…

function t:doAthing( paramA, paramB ) print( paramA, paramB ) end

or even like this…

local t = { doAthing = function( paramA, paramB ) print( paramA, paramB ) end } 

Now, if we look at the first version of that function, we can call it on it’s own, like this:

doAthing( "one thing", "another thing" )

Both of the parameters that we pass in get received inside the function as their named values.

But, once we’ve declared the function as a property of a table, we can call it “on the table”, like this…

t.doAthing( "one thing", "another thing" )

That is exactly the same as the previous call - both parameters are received exactly the same way.

We can also call it with the colon, which basically tells the function about the object which it is “being called on”, like this…

t:doAthing( "one thing", "another thing" )

The only difference here is that the two parameters, paramA and paramB, will be the table ‘t’ and the string “one thing” - “another thing” will get lost.

So, why is this useful?

Because you can write a function which doesn’t know anything about it’s parent object but still reference that parent object. Here’s what I mean…

Let’s say I want a function which will print a string property called “.class” of whatever table it is assigned to. I could create a bunch of tables all with different .class values…

local a = { class="first" } local b = { class="bee" } local c = { class="the sea" }

I could also create a function with the standard first parameter called ‘self’ and use that to get the table which the function has been assigned to (it doesn’t matter what that parameter is called, but ‘self’ is a convention.)…

local function printMyClass( self ) print( "My parent's class is: "..self.class ) end

I could then assign that function to all of those tables…

a.printMyClass = printMyClass b.printMyClass = printMyClass c.printMyClass = printMyClass

I can even create another one with the same class assigned to it but in a more creative way…

local d = { class = "I got a D :(" classPrinter = printMyClass }

So now, if I were to call all of those table’s printMyClass() functions they would print their parent’s .class property out - bear in mind that I effectively use a different name for the last one…

a:printMyClass() d:printMyClass() c:printMyClass() d:classPrinter()

And this would output…

first bee the sea I got a D :(

see horacebury’s reply, then… the “why” of the difference is because of two things:

  1.  things like .xScale are properties not methods , so you’d never call them with a colon, instead you access them with a period

  2.  methods on corona classes  (like display, audio, physics, etc) are called with a period, because there’s only ever one of them, so they have no need for a “self” parameter to distinguish “who” the method was called on.  otoh, methods on returned individual  instances (like rects, images, etc) are called with a colon, because they do need a “self” parameter to tell “who” the method was called on

hth

I got confused as well when I started corona.

I understand basically you only use the : if it is an object mothod.

So 

object:method()

object.property

class.property

class.mthod()

Not sure if I am 100% right

Yes, you are.

The short version of what I wrote earlier is that if you want a function as just a function on it’s own, you make it available to your code by calling it with a . on a table. This is like providing the table as a library object (like the math. namespace) and the function as just a function (e.g.: round() ) - Conversely, if you want a function on an object to do something for that object, you assign it to the object and call it with : (This gives you the benefit of being able to reuse functions by using ‘self’ or not, if you don’t want to.)