Colon notation in object-oriented programming

classic Classic list List threaded Threaded
36 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Colon notation in object-oriented programming

Dirk Laurie-2
2017-03-04 8:32 GMT+02:00 Petri Häkkinen <[hidden email]>:
> Why all the trouble? I mean, you could just use free functions:
> object_system_func(a, b, c)
>
> This is faster (no need for nested dynamic table look ups) and
> there is no need for "self" parameter that is magically more
> important than the others.

I and others replied to the above in the thread "Lua and composition",
but maybe it deserves a thread of its own.

Let me take an example from the only userdata objects supplied with
Lua, namely files.

One can write:

io.open("results.txt","w"):write(table.concat(results,"\n")):close()

Without colon notation, how far can we get?

local outfile = io.open("results.txt","w")

Now what next? Remember, outfile:write() is not available.
And io.write does not allow you to specify a file.

local filemeta = getmetatable(outfile).__index
filemeta.write(outfile,table.concat(results,"\n"))
filemeta.close(outfile)

Faster? Really? Clearer? Not on your nelly.

Now you can argue that the programmer is under no obligation
to hide the methods of a file object that well, but the point is that
you can't easily, by accident, call the write or close methods without
a valid file argument in place. This makes code safer and cleaner.

Reply | Threaded
Open this post in threaded view
|

Re: Colon notation in object-oriented programming

Petri Häkkinen
On Mar 5, 2017, at 1:32 PM, Dirk Laurie <[hidden email]> wrote:
> io.open("results.txt","w"):write(table.concat(results,"\n")):close()
>
> Without colon notation, how far can we get?

If there we no implicit self and no ':' sugar this would be written something like this:

local file = io.open("results.txt", "w")
io.write(file, table.concat(results, "\n"))
io.close(file)

Petri


Reply | Threaded
Open this post in threaded view
|

Re: Colon notation in object-oriented programming

Petri Häkkinen
On Mar 5, 2017, at 2:58 PM, Petri Häkkinen <[hidden email]> wrote:

> On Mar 5, 2017, at 1:32 PM, Dirk Laurie <[hidden email]> wrote:
>> io.open("results.txt","w"):write(table.concat(results,"\n")):close()
>>
>> Without colon notation, how far can we get?
>
> If there we no implicit self and no ':' sugar this would be written something like this:
>
> local file = io.open("results.txt", "w")
> io.write(file, table.concat(results, "\n"))
> io.close(file)


And to extend on my reply a little bit…  I don't think the difference between these two versions matter at all. Most of the CPU time is spent in file i/o and table.concat anyway (in the other thread I gave some examples where the speed difference can matter).

The original question was about object composition and extending the ':' notation and I was trying to say that it's actually valid to separate code and data (I.e. not  use OOP) and just use free functions to do your thing. I.e. instead of doing object.system:do_a_thing() or whatever just call object_system_do_a_thing() and pass whatever data you need in. You can still think of your data as objects, it's just the code that is written in imperative style. Simple.

The other ramblings I had were just about giving some ideas to people who may be too accustomed to think in only classes & object (I used to be one).

Hopefully I'm not sounding arrogant or besserwisser or anything like that. Just trying to be helpful.

Petri


Reply | Threaded
Open this post in threaded view
|

Re: Colon notation in object-oriented programming

Viacheslav Usov
In reply to this post by Dirk Laurie-2
On Sun, Mar 5, 2017 at 12:32 PM, Dirk Laurie <[hidden email]> wrote:

> but the point is that you can't easily, by accident, call the write or close methods without a valid file argument in place. This makes code safer and cleaner.

As mentioned here, http://lua-users.org/lists/lua-l/2017-02/msg00009.html , you can actually call the close method without a valid argument very easily, producing errors that are difficult to diagnose at times.

Fact is, the difference between the dot and the colon is very confusing and much back-stabbing for Lua neophytes, especially for those with experience in other object-oriented languages, where the dot means exactly what Lua denotes by the colon. Such people tend to make this mistake even after years of using Lua, if it is not their primary language.

Cheers,
V.
Reply | Threaded
Open this post in threaded view
|

Re: Colon notation in object-oriented programming

Soni "They/Them" L.
In reply to this post by Petri Häkkinen


On 05/03/17 10:25 AM, Petri Häkkinen wrote:

> On Mar 5, 2017, at 2:58 PM, Petri Häkkinen <[hidden email]> wrote:
>
>> On Mar 5, 2017, at 1:32 PM, Dirk Laurie <[hidden email]> wrote:
>>> io.open("results.txt","w"):write(table.concat(results,"\n")):close()
>>>
>>> Without colon notation, how far can we get?
>> If there we no implicit self and no ':' sugar this would be written something like this:
>>
>> local file = io.open("results.txt", "w")
>> io.write(file, table.concat(results, "\n"))
>> io.close(file)
>
> And to extend on my reply a little bit…  I don't think the difference between these two versions matter at all. Most of the CPU time is spent in file i/o and table.concat anyway (in the other thread I gave some examples where the speed difference can matter).
>
> The original question was about object composition and extending the ':' notation and I was trying to say that it's actually valid to separate code and data (I.e. not  use OOP) and just use free functions to do your thing. I.e. instead of doing object.system:do_a_thing() or whatever just call object_system_do_a_thing() and pass whatever data you need in. You can still think of your data as objects, it's just the code that is written in imperative style. Simple.
>
> The other ramblings I had were just about giving some ideas to people who may be too accustomed to think in only classes & object (I used to be one).
>
> Hopefully I'm not sounding arrogant or besserwisser or anything like that. Just trying to be helpful.
>
> Petri
>
>

Here's a challenge for you:

Write an extensible game modding API, using only static non-replaceable
functions, and without ever deferring to an object function inside them.

--
Disclaimer: these emails may be made public at any given time, with or without reason. If you don't agree with this, DO NOT REPLY.


Reply | Threaded
Open this post in threaded view
|

Re: Colon notation in object-oriented programming

Peter Aronoff
In reply to this post by Petri Häkkinen
Petri Häkkinen <[hidden email]> wrote:

> On Mar 5, 2017, at 1:32 PM, Dirk Laurie <[hidden email]> wrote:
> > io.open("results.txt","w"):write(table.concat(results,"\n")):close()
> >
> > Without colon notation, how far can we get?
>
> If there we no implicit self and no ':' sugar this would be written
> something like this:
>
> local file = io.open("results.txt", "w")
> io.write(file, table.concat(results, "\n"))
> io.close(file)

For what it’s worth, as someone who came to Lua without much OO experience,
I do exactly this now. I find procedural (or imperative) style far clearer.

P

--
We have not been faced with the need to satisfy someone else's
requirements, and for this freedom we are grateful.
    Dennis Ritchie and Ken Thompson, The UNIX Time-Sharing System

Reply | Threaded
Open this post in threaded view
|

Re: Colon notation in object-oriented programming

Dirk Laurie-2
2017-03-05 16:42 GMT+02:00 Peter Aronoff <[hidden email]>:

> Petri Häkkinen <[hidden email]> wrote:
>> On Mar 5, 2017, at 1:32 PM, Dirk Laurie <[hidden email]> wrote:
>> > io.open("results.txt","w"):write(table.concat(results,"\n")):close()
>> >
>> > Without colon notation, how far can we get?
>>
>> If there we no implicit self and no ':' sugar this would be written
>> something like this:
>>
>> local file = io.open("results.txt", "w")
>> io.write(file, table.concat(results, "\n"))
>> io.close(file)
>
> For what it’s worth, as someone who came to Lua without much OO experience,
> I do exactly this now. I find procedural (or imperative) style far clearer.

Have either of you adherents of `io.write(file, table.concat(results, "\n"))`,
one of whom claims to "do exactly this now", actually tried running that
line of code? If not, you have missed the point of that example and in
fact of my post.

Reply | Threaded
Open this post in threaded view
|

Re: Colon notation in object-oriented programming

Soni "They/Them" L.


On 05/03/17 11:48 AM, Dirk Laurie wrote:

> 2017-03-05 16:42 GMT+02:00 Peter Aronoff <[hidden email]>:
>> Petri Häkkinen <[hidden email]> wrote:
>>> On Mar 5, 2017, at 1:32 PM, Dirk Laurie <[hidden email]> wrote:
>>>> io.open("results.txt","w"):write(table.concat(results,"\n")):close()
>>>>
>>>> Without colon notation, how far can we get?
>>> If there we no implicit self and no ':' sugar this would be written
>>> something like this:
>>>
>>> local file = io.open("results.txt", "w")
>>> io.write(file, table.concat(results, "\n"))
>>> io.close(file)
>> For what it’s worth, as someone who came to Lua without much OO experience,
>> I do exactly this now. I find procedural (or imperative) style far clearer.
> Have either of you adherents of `io.write(file, table.concat(results, "\n"))`,
> one of whom claims to "do exactly this now", actually tried running that
> line of code? If not, you have missed the point of that example and in
> fact of my post.
>

Have you ever tried:

local myfile = {}

function myfile:write(...)
   local x = #self
   local t = {...}
   for i=1, select('#', ...) do
     self[x+i] = t[i]
   end
end

function myfile:close()
end

your_awful_function(myfile)

--
Disclaimer: these emails may be made public at any given time, with or without reason. If you don't agree with this, DO NOT REPLY.


Reply | Threaded
Open this post in threaded view
|

Re: Colon notation in object-oriented programming

Peter Aronoff
In reply to this post by Dirk Laurie-2
Dirk Laurie <[hidden email]> wrote:
> Have either of you adherents of `io.write(file, table.concat(results,
> "\n"))`, one of whom claims to "do exactly this now", actually tried
> running that line of code? If not, you have missed the point of that
> example and in fact of my post.

I haven’t tried that exact line. I suppose I have missed the point of that
example and your post (in fact!). Sorry.

My point was simply that I prefer to use procedural style. I never use the
colon in Lua. (In point of fact, if we’re going to be precise, I nearly
never use any of the functions in Lua’s io table “raw”. I have a small
module of wrapper methods that I use for convenience. But the principle
remains the same: I avoid the colon and prefer to pass the filehandle into
the method.)

Out of curiosity, what was your point?

P

--
We have not been faced with the need to satisfy someone else's
requirements, and for this freedom we are grateful.
    Dennis Ritchie and Ken Thompson, The UNIX Time-Sharing System

Reply | Threaded
Open this post in threaded view
|

Re: Colon notation in object-oriented programming

Peter Aronoff
Peter Aronoff <[hidden email]> wrote:
> Out of curiosity, what was your point?

Sigh. Apologies again. I think I (too late) see your point. To be honest,
I was responding more to the reply than to your original post (which I only
skimmed because I haven’t been following the latest 100-mail debate about
whatever it’s about).

I think your point is that `write` doesn’t let you specify what filehandle
to print to. If that’s correct, it’s exactly *why* I have a small module
with convenience methods. One of those methods allows the user to pass in
a filehandle, stores away the current output setting, temporarily sets the
filehandle as output, and the restores the original output.

If my guess is right, then I see your point, but I don’t see that it
requires OO notation or a colon.

How’d I do?

P

--
We have not been faced with the need to satisfy someone else's
requirements, and for this freedom we are grateful.
    Dennis Ritchie and Ken Thompson, The UNIX Time-Sharing System

Reply | Threaded
Open this post in threaded view
|

Re: Colon notation in object-oriented programming

Dirk Laurie-2
In reply to this post by Peter Aronoff
2017-03-05 17:26 GMT+02:00 Peter Aronoff <[hidden email]>:

> Dirk Laurie <[hidden email]> wrote:
>> Have either of you adherents of `io.write(file, table.concat(results,
>> "\n"))`, one of whom claims to "do exactly this now", actually tried
>> running that line of code? If not, you have missed the point of that
>> example and in fact of my post.
>
> I haven’t tried that exact line. I suppose I have missed the point of that
> example and your post (in fact!). Sorry.
>
> My point was simply that I prefer to use procedural style. I never use the
> colon in Lua. (In point of fact, if we’re going to be precise, I nearly
> never use any of the functions in Lua’s io table “raw”. I have a small
> module of wrapper methods that I use for convenience. But the principle
> remains the same: I avoid the colon and prefer to pass the filehandle into
> the method.)
>
> Out of curiosity, what was your point?

The point of the example is that `io` is not the metatable, or the __index
metamethod, of a file. In fact,

Reply | Threaded
Open this post in threaded view
|

Re: Colon notation in object-oriented programming

Dirk Laurie-2
In reply to this post by Soni "They/Them" L.
2017-03-05 16:56 GMT+02:00 Soni L. <[hidden email]>:

> Have you ever tried:
> ...
> function myfile:write(...)
>   local x = #self
...

No ... but I habitually put in my programs

local append = function(tbl,obj,...)
  if ... then obj = obj:format(...) end
  table.insert(tbl,obj)
end

Reply | Threaded
Open this post in threaded view
|

Re: Colon notation in object-oriented programming

Soni "They/Them" L.


On 05/03/17 01:38 PM, Dirk Laurie wrote:

> 2017-03-05 16:56 GMT+02:00 Soni L. <[hidden email]>:
>
>> Have you ever tried:
>> ...
>> function myfile:write(...)
>>    local x = #self
> ...
>
> No ... but I habitually put in my programs
>
> local append = function(tbl,obj,...)
>    if ... then obj = obj:format(...) end
>    table.insert(tbl,obj)
> end
>
I meant calling one of those "static file functions" with a custom
"virtual" file that writes to a table instead of writing to an actual file.

Also, file:write() takes a varargs.

--
Disclaimer: these emails may be made public at any given time, with or without reason. If you don't agree with this, DO NOT REPLY.


Reply | Threaded
Open this post in threaded view
|

Re: Colon notation in object-oriented programming

Petri Häkkinen
In reply to this post by Soni "They/Them" L.
On Mar 5, 2017, at 4:26 PM, "Soni L." <[hidden email]> wrote:
> Here's a challenge for you:
>
> Write an extensible game modding API, using only static non-replaceable functions, and without ever deferring to an object function inside them.

Sorry, I don't understand. What's an "object function" and "static non-replaceable function"? In Lua there is just one function type.

Also, I don't see how not using "self" would stop me from writing a modding API.

Petri


Reply | Threaded
Open this post in threaded view
|

Re: Colon notation in object-oriented programming

Petri Häkkinen
In reply to this post by Dirk Laurie-2
On Mar 5, 2017, at 4:48 PM, Dirk Laurie <[hidden email]> wrote:
> Have either of you adherents of `io.write(file, table.concat(results, "\n"))`,
> one of whom claims to "do exactly this now", actually tried running that
> line of code? If not, you have missed the point of that example and in
> fact of my post.
>

I know it does not work. That's why I said "If there were no implicit self and no ':' sugar" (although I typoed "were").




Reply | Threaded
Open this post in threaded view
|

Re: Colon notation in object-oriented programming

Soni "They/Them" L.
In reply to this post by Petri Häkkinen


On 05/03/17 01:53 PM, Petri Häkkinen wrote:

> On Mar 5, 2017, at 4:26 PM, "Soni L." <[hidden email]> wrote:
>> Here's a challenge for you:
>>
>> Write an extensible game modding API, using only static non-replaceable functions, and without ever deferring to an object function inside them.
> Sorry, I don't understand. What's an "object function" and "static non-replaceable function"? In Lua there is just one function type.
>
> Also, I don't see how not using "self" would stop me from writing a modding API.
>
> Petri
>
>

Write a modding API where you use

get_inventory_item(something, slot) -- aka a "static non-replaceable
function"

And "get_inventory_item" cannot be replaced and you don't call a
function from "something" through it. So e.g. no

function get_inventory_item(something, slot)
   return something.get_inventory_item(something, slot) -- aka an
"object function"
end

And no having a lookup table to map objects to functions.

--
Disclaimer: these emails may be made public at any given time, with or without reason. If you don't agree with this, DO NOT REPLY.


Reply | Threaded
Open this post in threaded view
|

Re: Colon notation in object-oriented programming

Petri Häkkinen
On Mar 5, 2017, at 6:57 PM, "Soni L." <[hidden email]> wrote:

> Write a modding API where you use
>
> get_inventory_item(something, slot) -- aka a "static non-replaceable function"
>
> And "get_inventory_item" cannot be replaced and you don't call a function from "something" through it. So e.g. no
>
> function get_inventory_item(something, slot)
>  return something.get_inventory_item(something, slot) -- aka an "object function"
> end
>
> And no having a lookup table to map objects to functions.


function get_inventory_item(obj, slot)
  if obj.inv then
    return obj.inv[slot]
  end
end

Sorry couldn't resist :)

You probably want opaque objects (don't want the inventory table to be directly accessible on user side):

local inventories = {}

function get_inventory_item(obj, slot)
  local inv = inventories[obj]
  if inv then
    return inv[slot]
  end
end

:-)
 
Petri


Reply | Threaded
Open this post in threaded view
|

Re: Colon notation in object-oriented programming

Francisco Olarte
In reply to this post by Viacheslav Usov
On Sun, Mar 5, 2017 at 3:01 PM, Viacheslav Usov <[hidden email]> wrote:
> Fact is, the difference between the dot and the colon is very confusing and
> much back-stabbing for Lua neophytes, especially for those with experience
> in other object-oriented languages, where the dot means exactly what Lua
> denotes by the colon. Such people tend to make this mistake even after years
> of using Lua, if it is not their primary language.

My problem with colon is that, being used to languages which use dot
for everything, I routinely end up writing obj.method(a,b,c), which is
perfectly legal lua ( and luacheck ) and ends up producing tedious to
debug  runtime errors later on.

I'm used to languages which separate 'methods' and data, like C++ (
which, both being statically typed can do the proper thing with the
dot depending on the decl ) or even perl ( where you do
$obj->method(...) or $obj->{function}->(...) ), and it bites me every
single day. I alleviate it by grepping periodically on the source (
for '\w+\.\w+\(' ) and stashing the rarely used function call in
locals ( obj:method(), but local f=obj.func; f(...) ), but is one of
the major pains I encounter when doing moderately complex code in lua.

Regards.
   Francisco Olarte

Reply | Threaded
Open this post in threaded view
|

Re: Colon notation in object-oriented programming

Francisco Olarte
In reply to this post by Peter Aronoff
Peter:

On Sun, Mar 5, 2017 at 3:42 PM, Peter Aronoff <[hidden email]> wrote:
> Petri Häkkinen <[hidden email]> wrote:
>> local file = io.open("results.txt", "w")
>> io.write(file, table.concat(results, "\n"))
>> io.close(file)
>
> For what it’s worth, as someone who came to Lua without much OO experience,
> I do exactly this now. I find procedural (or imperative) style far clearer.

Did not you notice io.write is not necessarily the same as file.write?

Francisco Olarte.

Reply | Threaded
Open this post in threaded view
|

Re: Colon notation in object-oriented programming

Francisco Olarte
In reply to this post by Petri Häkkinen
On Sun, Mar 5, 2017 at 5:53 PM, Petri Häkkinen <[hidden email]> wrote:
> Also, I don't see how not using "self" would stop me from writing a modding API.

Nothing.

You can easily do OO programming in assembler, where your objects are
memory data blocks inside which there is a pointer to a jump table,
IIRC Linux kernel does this in C for several things and C++ translate
into a version of it. In fact things like C FILE* are clearly OO and
in some libs FILE* are even polymorphic.

But I doubt that is the point. I, personally, normally use OO style
when I find it easier or clearer.


Francisco Olarte.

12