Prototype languages and programming

General discussion about LÖVE, Lua, game development, puns, and unicorns.
Post Reply
User avatar
Inny
Party member
Posts: 652
Joined: Fri Jan 30, 2009 3:41 am
Location: New York

Prototype languages and programming

Post by Inny »

I have a bit of an advanced topic I'd like to talk about, half of it is spreading what I think I've learned and half is asking if I'm correct and is this worth it. That question is how to use the prototype programming model properly, rather than just building a class system on top of it and returning to object oriented programming. For anyone new to this idea, start here: https://en.wikipedia.org/wiki/Prototype ... rogramming

Prototype Based Languages are ones where there are only objects, and no classes. Lua, Javascript, and lesser known languages like Io and Self, and to get technical, Python and Ruby (though they strongly advise you to ignore the man behind the curtain). To contrast, in C++ and Java, there's no real "Class Object", in the sense that the Class is really a declaration and wouldn't store any introspection information in memory. There's no "address" of a class object in C++, where as every table in Lua has an address. So, that's the difference from a technical standpoint.

However, and this is the point where I wasn't sure to move forward from, Classes offer features like "constructors." In lua, this is easy to get back. In kikito's middleclass library, it's the initialize function. However, that creates a subdivision between Classes and Instances, since only instances get initialized, and initializing a Class object in a hierarchy of inheritance is nonsensical. In a Prototype system, inheritance is called "cloning", and with objects that just clone each other, how would you construct those last objects? For a programmer, it would kind of mean manually building the specialized object at the point you use it, which sounds like a hassle and probably breaks any kind of encapsulation.

So, I did some research, and the best pattern I could see being used in prototype langauges, besides getting back to classes, is just to do function chaining. I'll demonstrate with some code:

Code: Select all

-- parent object of all objects
Object = {
  clone = function( self, proto )
    proto = proto or {}
    proto.__index = self
    return setmetatable(proto, proto)
  end
}

-- Some container
Foo = Object:clone {
  x = 27,
  init = function(self, y)
    self.y = y
    return self
  end
  setX = function(self, x)
    self.x = x
    return self
  end
}

-- Lacking any kind of constructor
bar = Foo:clone():init( 42 ):setX( 2993 )

print( Object, Foo, Foo.x, bar, bar.x, bar.y )
So, am I correct, am I alone in figuring this out, or am I totally wrong, and is this a waste of time?
User avatar
vrld
Party member
Posts: 917
Joined: Sun Apr 04, 2010 9:14 pm
Location: Germany
Contact:

Re: Prototype languages and programming

Post by vrld »

Your method works, but can have unwanted side effects when something overwrites parent fields that are not yet defined in the clone. Using your example:

Code: Select all

baz = Foo:clone()
Foo.x = 23
print(bar.x, baz.x) --> 2993	23
IMO it's better to do a deep copy of the object, like this (untested):

Code: Select all

Object = {}
function Object:clone()
    local visited = {}
    local function deep_copy(t)
        if visited[t] then return visited[t] end

        local copy = {}
        for k,v in pairs(t) do
             copy[k] = type(v) == 'table' and deep_copy(v) or v
        end

        visited[t] =  copy
        return  copy
    end

    return deep_copy(self)
end
Translating your example to the new code produces:

Code: Select all

Foo = Object:clone()
Foo.x = 27
function Foo:init(y) self.y = y; return self; end
function Foo:setX(x) self.x = x; return self; end -- btw: I think getters/setters are evil and should be avoided

bar = Foo:clone()
bar:init(42):setX(2993)

print(Foo.x, bar, bar.x, bar.y) --> 27	table: 0xsomething	2993	42
I have come here to chew bubblegum and kick ass... and I'm all out of bubblegum.

hump | HC | SUIT | moonshine
User avatar
Inny
Party member
Posts: 652
Joined: Fri Jan 30, 2009 3:41 am
Location: New York

Re: Prototype languages and programming

Post by Inny »

I'm not a fan of deep-copying during a clone. Plus, the missing member in the parent was probably an omission on my part. I was more asking if the design pattern at play here with chaining functions as an alternate to a constructor function is legit. The evidence I have that it is, is that jQuery and Underscore.js use that pattern of chaining.
Post Reply

Who is online

Users browsing this forum: pgimeno and 6 guests