[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: More on environments and objects
- From: Chris Marrin <chris@...>
- Date: Fri, 26 Aug 2005 07:35:19 -0700
I have been thinking more about the issue of separate environments and
how that helps with an object-oriented approach to Lua, with C++ object
interactions. As Rici has pointed out, when you have a function
representing an object method you really want its environment to be
something common to all instances of this object type. Otherwise you
will be creating functions for every instance, which would not only
bloat memory some, but would take time as well.
If you did have an environment common to all instances of an object
type, then it could have an __setindex metamethod. Let's say we have a
class called MyClass with an __call metamethod to do instantiation.
Further, let's say this class has a member variable 'a' and a member
function 'f' defined like this:
Function MyClass:f(v) a = v end
then you could go:
local instance = MyClass()
instance:f(5)
and when f(v) runs, the __setindex metamethod would get called with the
parameters of the common function environment, the property 'a' and the
value 'v'. This __setindex method can then go up to the next function to
the stack and find the 'self' reference as the first param. It can then
look up 'a' in this reference, set its value to 'v' and you're done. A
nice object-oriented mechanism for handling instance local access.
The problem with this is that you don't really KNOW if the first
parameter to the function is the 'self' reference. It may have been
called using the SELF opcode to setup the stack. But that fact doesn't
leave behind any clues. This is because this:
instance:f(5)
is equivalent to:
instance.f(instance, 5)
in Lua. That is really too bad. It can lead to very tough to debug
errors. I know that, even though I have been writing Lua for several
months now I still often use '.' when I intended to use ':'. Often this
is easy to catch: the param after 'self' is something that looks nothing
like a self pointer, so an error is generated. But what if you are
passing an object that looks like a self pointer as the first param? You
might have a function like this:
function MyClass:g(v)
if v ~= nil then
self.a = v.a
else
self.a = 10
end
end
If you call this like this:
local instance2 = MyClass()
instance2.a = 5
instance:g(instance2)
it works fine. After the call instance.a is 5. But if you do this instead:
instance.g(instance2)
then you change instance2.a to 10, which was not the intent. No error is
issued and it might be very difficult to track this down.
It would not be hard to add something to CallInfo to indicate that this
method was called with the SELF instruction. That would no longer allow
this:
instance.g(instance, instance2)
in place of this:
instance:g(instance2)
but it would still be compatible because I'm making the ':' syntax a
requirement in my object system. The rest of Lua works as it always has.
Anyway, does this seem like a reasonable approach?
--
chris marrin ,""$, "As a general rule,don't solve puzzles
chris@marrin.com b` $ that open portals to Hell" ,,.
,.` ,b` ,` , 1$'
,|` mP ,` :$$' ,mm
,b" b" ,` ,mm m$$ ,m ,`P$$
m$` ,b` .` ,mm ,'|$P ,|"1$` ,b$P ,` :$1
b$` ,$: :,`` |$$ ,` $$` ,|` ,$$,,`"$$ .` :$|
b$| _m$`,:` :$1 ,` ,$Pm|` ` :$$,..;"' |$:
P$b, _;b$$b$1" |$$ ,` ,$$" ``' $$
```"```'" `"` `""` ""` ,P`