Page 3 of 25

Re: MiddleClass & MindState: Object Orientation for LUA

Posted: Wed Apr 14, 2010 7:43 pm
by blenderer
problem resolved, thanks

Re: MiddleClass & MindState: Object Orientation for LUA

Posted: Wed Apr 14, 2010 7:55 pm
by bartbes
I solved it on IRC, it was another : vs . error.

Re: MiddleClass & MindState: Object Orientation for LUA

Posted: Wed Apr 14, 2010 8:19 pm
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.

Re: MiddleClass & MindState: Object Orientation for LUA

Posted: Wed Apr 14, 2010 10:19 pm
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.

Re: MiddleClass & MindState: Object Orientation for LUA

Posted: Wed Apr 14, 2010 11:59 pm
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.

Re: MiddleClass & MindState: Object Orientation for LUA

Posted: Thu Apr 15, 2010 11:51 am
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.

Re: MiddleClass & MindState: Object Orientation for LUA

Posted: Thu Apr 15, 2010 10:32 pm
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?

Re: MiddleClass & MindState: Object Orientation for LUA

Posted: Thu Apr 15, 2010 10:39 pm
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:

Re: MiddleClass & MindState: Object Orientation for LUA

Posted: Fri Apr 16, 2010 7:15 am
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.

Re: MiddleClass & MindState: Object Orientation for LUA

Posted: Wed Apr 21, 2010 11:04 pm
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?