middleclass & extras: middleclass 3.0 is out!

Showcase your libraries, tools and other projects that help your fellow love users.
blenderer
Prole
Posts: 16
Joined: Fri Feb 12, 2010 1:19 am

Re: MiddleClass & MindState: Object Orientation for LUA

Post by blenderer »

problem resolved, thanks
Last edited by blenderer on Wed Apr 14, 2010 7:56 pm, edited 1 time in total.
User avatar
bartbes
Sex machine
Posts: 4946
Joined: Fri Aug 29, 2008 10:35 am
Location: The Netherlands
Contact:

Re: MiddleClass & MindState: Object Orientation for LUA

Post by bartbes »

I solved it on IRC, it was another : vs . error.
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: MiddleClass & MindState: Object Orientation for LUA

Post by kikito »

ah, I hate those.

The : operator is actually one of the only things I don't like much about Lua. I wish it was reversed - so the dot included "self" by default and the colon didn't. That, and variables being local by default.
When I write def I mean function.
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: MiddleClass & MindState: Object Orientation for LUA

Post by Robin »

kikito wrote:ah, I hate those.

The : operator is actually one of the only things I don't like much about Lua. I wish it was reversed - so the dot included "self" by default and the colon didn't.
No you don't. ;)
Consider this:

Code: Select all

love:graphics:print(self:class:name, self:x, self:y)
kikito wrote:That, and variables being local by default.
P*thon does that, but Lua's way has two distinctive advantages:
  1. You have more control over what “local” means. (Inside this module? Inside this function? In this loop? Is it perhaps an upvalue?)
  2. Lua is a configuration language from origin, which means encapsulation is usually a bad thing.
Help us help you: attach a .love.
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: MiddleClass & MindState: Object Orientation for LUA

Post by kikito »

Robin wrote:No you don't. ;)
Consider this:

Code: Select all

love:graphics:print(self:class:name, self:x, self:y)
That is not what I meant. Let me be a bit more precise: First, I only meant it to be used on method calls: love.graphics, self.class.name, self.x, self.y would work just the same as they do.

The only difference would be love.graphics.print. On that call, love.graphics would be sent to that function as a parameter called self. But you would be completely free to ignore it if you wanted to on your function definition:

Code: Select all

function love.graphics.print(...)
  -- I don't use self here anyway
The thing is, most of the time, when you do something.method() you do want to make something self. If you don't want to, you can safely ignore that extra self parameter. And for those weird cases when you really can't afford an extra parameter, the invocation could be done with :.

This is the schema used on javascript.
Robin wrote: P*thon does that, but Lua's way has two distinctive advantages:
  1. You have more control over what “local” means. (Inside this module? Inside this function? In this loop? Is it perhaps an upvalue?)
  2. Lua is a configuration language from origin, which means encapsulation is usually a bad thing.
I'm talking about mere syntax here. Forgetting to write "local" in front of a local variable is just too easy.
I'd rather have a "global" keyword, and have locals defined by default. This would not only change the "configurationness" of the language in that you would have to write "global" in front of the configuration variables.
And you would still have the same level of control; still locals and globals. Just changed the way you declare them.
When I write def I mean function.
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: MiddleClass & MindState: Object Orientation for LUA

Post by Robin »

kikito wrote:That is not what I meant. Let me be a bit more precise: First, I only meant it to be used on method calls: love.graphics, self.class.name, self.x, self.y would work just the same as they do.

The only difference would be love.graphics.print. On that call, love.graphics would be sent to that function as a parameter called self. But you would be completely free to ignore it if you wanted to on your function definition:

Code: Select all

function love.graphics.print(...)
  -- I don't use self here anyway
The thing is, most of the time, when you do something.method() you do want to make something self. If you don't want to, you can safely ignore that extra self parameter. And for those weird cases when you really can't afford an extra parameter, the invocation could be done with :.
How about:

Code: Select all

function foo()
  -- what is 'self' here?
end
a={}
function a.foo()
end
foo = a.foo
foo() -- what is 'self' here?

return function () print(#self) end -- what is 'self' here?
The thing is, with the : syntax there is no ambiguity over what the “self” parameter means.
kikito wrote:I'm talking about mere syntax here. Forgetting to write "local" in front of a local variable is just too easy.
I'd rather have a "global" keyword, and have locals defined by default. This would not only change the "configurationness" of the language in that you would have to write "global" in front of the configuration variables.
And you would still have the same level of control; still locals and globals. Just changed the way you declare them.
That's not what I meant. ;)

What would this print?

Code: Select all

function foobar()
    i = 0 -- remember: local by default
    for j=1,20 do
        i = j + 1
    end
    print(i)
    do
        i = 'hi'
    end
    print(i)
end
Having said all this, I'm tired. Let's talk about something else.
Help us help you: attach a .love.
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: MiddleClass & MindState: Object Orientation for LUA

Post by kikito »

self in all cases would be defined by the caller (the foo in foo.bar()). If no caller, self would be nil.

Code: Select all

def f() print(self~=nil) end
a.f = f
f() --false
a.f() -- true
The second code would print the same as in regular lua, if the first line of the function started with local i = 0.

But yes, let's move to something else. I'd like to know your opinion about something.

StatefulObjects have an internal stack on which they pile "states". Their index function (usually, a method call) looks on that stack, in reverse order. But when they look for a method on a state, they actually look on the state first, then on the state's "father state", etc. It might be easier to explain with a graph.

Say you have a class A that is a subclass of StatefulObject. You add 3 states to that class, named x,y,z. You add some methods to those states.
Then you subclass A with a class called B. That class "comes" with automatically created "substates" of x,y,z. You modify some methods on those.
Finally you do the same with a class called C.

Now, you create an instance of C, and push the 3 states on its state pile:

Code: Select all

c = C:new()
c:pushState('x')
c:pushState('y')
c:pushState('z')
And then you do: c:foo()

This is what lua will do to look for foo:

Code: Select all

              +---+     +---+     +---+
   CLASS A    | x |  +--| y |  +--| z |
              +---+  |  +---+  |  +---+
                Î    |    Î    |    Î
              +---+  |  +---+  |  +---+
   CLASS B    | x |  |  | y |  |  | z |
              +---+  |  +---+  |  +---+
                Î    |    Î    |    Î
              +---+  |  +---+  |  +---+
   CLASS C    | x |<-+  | y |<-+  | z | <-- We start looking for foo here
              +---+     +---+     +---+
This is the core functionality of StatefulObjects, so I want to make it as efficient as possible.

Here is the relevant code:

Code: Select all

  classDict.__index = function(instance, methodName)
      ...
      local stack = _private[instance].stateStack -- stack is a regular lua table
      local method
      for i = #stack,1,-1 do -- reversal loop
        method = stack[i][methodName]
        if(method~=nil) then return method end
      end
    end
    --if not found, look on the class
    return classDict[methodName]
  end
My questions are:
  • Any obvious deffects?
  • Any possible optimization strategies?
When I write def I mean function.
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: MiddleClass & MindState: Object Orientation for LUA

Post by Robin »

kikito wrote:
  • Any obvious deffects?
  • Any possible optimization strategies?
Not as far as I can tell.

One thing you could change (not sure whether it will matter for anything though), is this:

Code: Select all

  classDict.__index = function(instance, methodName)
      ...
      local stack = _private[instance].stateStack -- stack is a regular lua table
      for i = #stack,1,-1 do -- reversal loop
        local method = stack[i][methodName] -- you don't need 'method' outside of this for loop.
        if(method~=nil) then return method end -- also, if you don't care about false values, you can change this to 'if method then ...'
      end
    end
    --if not found, look on the class
    return classDict[methodName]
  end
My questions are:
Help us help you: attach a .love.
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: MiddleClass & MindState: Object Orientation for LUA

Post by kikito »

Thanks for the feedback.

I do care about false values - someone can define a A.PRINT_DEBUG_MESSAGES = true variable.

I was hoping there was a more efficient way of doing this using more __index stuff and les for ... stuff. But this one works. And objects shouldn't really pile more than two or 3 states anyway, so it shouldn't be a big deal.
When I write def I mean function.
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: MiddleClass & MindState: Object Orientation for LUA

Post by kikito »

I've moved away from code.google.com to the greener pastures of github.

NEW MIDDLECLASS page on github.

One question for anyone using MiddleClass:

I'm planning to remove the getter/setter stuff out of the core middleclass and into a mixin, so it can be used only on those classes that need it.

Would this change somehow affect anyone?
When I write def I mean function.
Post Reply

Who is online

Users browsing this forum: No registered users and 51 guests