OO - keeping lua as lua

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

OO - keeping lua as lua

Adrian Sietsma
There has been a lot of mail on this list re Lua and Object Oriented
Programming, functional programming, etc.

I have some views (who hasn't) on this.

1/ Lua already supports (mimics?) OOP via the metatable / proxy table
approach

2/ A lot of OOP is about encapsulationg, hiding and protecting data,
methods, etc., as well as the inheritance issues. This is all very well,
but Lua allows me to do things that are anathema to OOP, particularly
adding new members to an existing object.
eg

t = newobject(...)
t.x_descript = "zorro" -- add member var to object

f = io.open(file)
getmetatable(f).newfunc = new_metafunc -- add class function

new_open = function(...) return io_open(...) end
io.open,io_open = new_open, io.open	-- re-vector method


do i want users of my C++ libraries to do that ? no.
do i want to do that to other C++ libraries ? no. (not often)
do i want users of my Lua libraries to do that ? why ever not!
do i want to do that to other libraries ? of course!

apart from anything else, it makes library extensions easier. i use an
extended os.lib - would i rather type os.dir() or os_aux.dir() ?
also - if i were to write LuaSound, fred (i don't think there are any
freds on the list) could write a whole heap of nifty add-ons, and build
an extended lib, without my involvement. which is good.

none of this says that you can't make un-modifiable objects, classes,
etc : but it would be wrong for this to be the default.

might i suggest that a lua.class library could be an interesting way to
encapsulate a pure OO syntax. this would also be a lua-ish way to do
things, without changing the core.
(a class being a userdata may be interesting : store per-object data in
the metatable, and use the __index metafunc to give
obj.method() and obj.attribute syntax, if you like)

Adrian






Reply | Threaded
Open this post in threaded view
|

Re: OO - keeping lua as lua

D Burgess-4
I agree Adiran.
The core is pretty good as is.

Reply | Threaded
Open this post in threaded view
|

Re: OO - keeping lua as lua

Steve Donovan-2
In reply to this post by Adrian Sietsma
>>> [hidden email] 01/25/05 10:07AM >>>
>1/ Lua already supports (mimics?) OOP via the metatable / proxy table
>approach

Absolutely - and it works very well.  Most proposals involve
extra syntactical sugar, and Lua is very light on the calories!

>2/ A lot of OOP is about encapsulationg, hiding and protecting data,
>methods, etc., as well as the inheritance issues. This is all very
well,
>but Lua allows me to do things that are anathema to OOP, particularly
>adding new members to an existing object.

And why not?  Anathema to a particular OOP doctrine, perhaps.
Why impose Java/C++ styles on such a flexible language?

We can learn from the Smalltalk tradition, straight
or via Objective-C, but we don't have to pick up restrictive
attitudes in the process.

steve d.





Reply | Threaded
Open this post in threaded view
|

Re: OO - keeping lua as lua

David Given
In reply to this post by Adrian Sietsma
On Tuesday 25 January 2005 08:07, Adrian Sietsma wrote:
[...]
> do i want users of my C++ libraries to do that ? no.
> do i want to do that to other C++ libraries ? no. (not often)
> do i want users of my Lua libraries to do that ? why ever not!
> do i want to do that to other libraries ? of course!

May I remind everyone of Flon's Axiom?

There does not now, nor will there ever, exist a programming language in which 
it is the least bit hard to write bad programs.

My general opinion of languages with enforced data hiding is that (a) you 
cannot stop the user being a muppet; (b) enforced data hiding is a pain from 
the programmer's point of view; (c) therefore it's far easier to simply not 
bother. Document the fields and methods as being internal, and if the user 
plays with them, that's it's problem.

(Incidentally, I'm agreeing with you.)

-- 
+- David Given --McQ-+ "Gaping from its single obling socket was
|  [hidden email]    | scintillating, many fauceted scarlet emerald..."
| ([hidden email]) | --- Jim Theis, _The Eye of Argon_ (spelling
+- www.cowlark.com --+ original)

Reply | Threaded
Open this post in threaded view
|

Re: OO - keeping lua as lua

Mark Hamburg-4
on 1/25/05 2:38 AM, David Given at [hidden email] wrote:

> My general opinion of languages with enforced data hiding is that (a) you
> cannot stop the user being a muppet; (b) enforced data hiding is a pain from
> the programmer's point of view; (c) therefore it's far easier to simply not
> bother. Document the fields and methods as being internal, and if the user
> plays with them, that's it's problem.

I like that position until it hits the issue of having users not be the same
as the one's potentially writing code. For example, if I publish the APIs to
my system so that it can be extended by others, the consumers of such
extensions are not necessarily the authors of the extensions. I can see an
argument for wanting to protect consumers from sloppy or malicious authors.
An extension script might not work, but it would be nice if it couldn't
cause damage throughout the system.

That being said, I think Lua's syntax is fine with respect to supporting the
polymorphic aspect of object-oriented programming. Lua's support for
inheritance doesn't work as transparently as in some languages built around
inheritance, but it's usable (and I personally find inheritance over-rated).
So, solving the encapsulation problem in a simple, efficient manner is
probably my top concern to the extent that I have one.

(I've actually been spending more time thinking about how to make GC for
semi-weak tables work without having cycle problems -- though if that worked
it's one way to achieve encapsulation.)

Mark


Reply | Threaded
Open this post in threaded view
|

Re: OO - keeping lua as lua

Petite Abeille

On Jan 25, 2005, at 18:29, Mark Hamburg wrote:

I can see an argument for wanting to protect consumers from sloppy or malicious authors.

What would be that argument? Getting out of your way to _enforce_ some notion of what is good and what is not is a bit condescending to your potential users, no?

In any case, nothing beat good, old fashioned documentations :)

An extension script might not work, but it would be nice if it couldn't
cause damage throughout the system.

If it's so important for your project to protect the innocents from themselves, then "sandbox" your application/library/whatnot one way or another. But this seems to be a lost cause: if people want to shot themselves in the foot, they will, no matter what.

Cheers

--
PA
http://alt.textdrive.com/


Reply | Threaded
Open this post in threaded view
|

Re: OO - keeping lua as lua

skaller
On Wed, 2005-01-26 at 04:43, PA wrote:
> On Jan 25, 2005, at 18:29, Mark Hamburg wrote:
> 
> > I can see an argument for wanting to protect consumers from sloppy or 
> > malicious authors.
> 
> What would be that argument? Getting out of your way to _enforce_ some 
> notion of what is good and what is not is a bit condescending to your 
> potential users, no?

Really?

Do you feel condescended to when I provide you a function,
and you can't get at the local variables of the function?

You, the programmer CAN get at the local variables,
in fact you can edit the function!

But given the function -- or any other function,
including one you yourself edited, the code
that calls it can't get at its local variables,
or any of its implementation for that matter.

As I'm sure you know this means you can reprogram
the function to make it more efficient, or fix a bug,
without client code being affected... that's surely
useful to you -- as the functions author -- and also
you -- as the functions client.

Well, as I see it a class is just a collection of
functions with some 'local variables' shared between
then, namely the private data of the object.

So it just looks like a bug if you can't hide that
data the same way you can hide the private parts
of a single function. Using my implementation,
which is to return a table of closures,
the private members are hidden precisely
*because* the technique uses lexical scoping
and closures:

	function class(args)
		local x = ..
		local y = ..
		function method1 (..) .. end
		function method2 (.. ) .. end
		return { ["f"]=method1, ["g"]=method2..}
	end

With some sugar this would be

	class X(args)
		local x = .
		local y = ..
		method f(..) ..end
		method g(..) .. end
	end


The sugar is trivial to implement, and the result
looks very OO .. the main problem as pointed out
is that this doesn't allow for inheritance,
and those locals are wholly private, not merely
protected.

However no 'self' is required in the method
definitions, and you can just use

	x.f (args)

to call a method -- since he result is just a table x,
with key "f" for method f.

So this is the minimal change to get classes with
proper encapsulation, and only requires sugar in
the interpreter, and no core changes at all.

To get inheritance you might try this sugar:

	inherit B(args)

which, when used in a class calls the function B,
grabs the resulting table, and then modifies
it with the current class methods.

Actually, even better -- you start with an empty table
and pass it in to the inherited function to populate,
and then you get multiple inheritance for free:

	class X(args)
		local x ..
		local y .
		method f(..) ...
		inherit A (..)
		method g( .. )
		inherit B ( ..)
		method h (.. )
	end

This is quite interesting -- f goes in the table first,
then A's methods, then g, then B's methods, then h.
This means A can actually override f, and B can override
anything A put in, as well as f and g.

This whole thing would be syntactic sugar and
the result is just an ordinary table without
any metamethods .. which means the user can
add the usual metamethods if they want, the
system doesn't ursurp them.

Note you can still have public members, suppose the
table is called __methods then

	__methods['a'] = 1

would just add the variable a to the method table
(as well as the methods), and you could do:

	x.a = 2

and even add things like

	x.b = 42 -- new variable added!
	x.c = function .. end -- new method added

Only tricky thing is passing the __methods table in for
inherits .. but not needing it for a client
constructor, so it should default to {},
but the actual default is 'nil' ..  so you'd
need to add

	if __methods == nil then _method = {} end

at the top of each class body.

-- 
John Skaller, [hidden email]
voice: 061-2-9660-0850, 
snail: PO BOX 401 Glebe NSW 2037 Australia
Checkout the Felix programming language http://felix.sf.net




Reply | Threaded
Open this post in threaded view
|

Re: OO - keeping lua as lua

Mark Hamburg-4
In reply to this post by Petite Abeille
on 1/25/05 9:43 AM, PA at [hidden email] wrote:

> 
> On Jan 25, 2005, at 18:29, Mark Hamburg wrote:
> 
>> I can see an argument for wanting to protect consumers from sloppy or
>> malicious authors.
> 
> What would be that argument? Getting out of your way to _enforce_ some
> notion of what is good and what is not is a bit condescending to your
> potential users, no?

Trashing the user's database is unlikely to be viewed as good. Destabilizing
the application is unlikely to be viewed as good.

The feature for users from protection is that they can feel a bit more
confident in running scripts they didn't write themselves.

> In any case, nothing beat good, old fashioned documentations :)

My users aren't script writers. They are script consumers. Documenting how
to use the system won't protect them.

>> An extension script might not work, but it would be nice if it couldn't
>> cause damage throughout the system.
> 
> If it's so important for your project to protect the innocents from
> themselves, then "sandbox" your application/library/whatnot one way or
> another. But this seems to be a lost cause: if people want to shot
> themselves in the foot, they will, no matter what.

The issue is that sandboxing data is relatively difficult, but see my longer
message from this morning on ways to do it.

Mark


Reply | Threaded
Open this post in threaded view
|

Re: OO - keeping lua as lua

Petite Abeille
In reply to this post by skaller

On Jan 25, 2005, at 19:29, skaller wrote:

Really?

Really.

Do you feel condescended to when I provide you a function,
and you can't get at the local variables of the function?

You are entirely missing the point... déjà vu?

Lua, out-of-the-box, already provides this functionality at the, er, function level. Even though, you could get to local variables if you really wanted to for some obscure reasons:

http://www.lua.org/pil/23.1.1.html

In the thread at hand, I was under the impression that we where talking about "packaging" Lua's existing functionalities to make them a tad more "object oriented"... what "a tad more 'object oriented'" means in practice, and in the context of Lua, is left as an exercise to the interested reader...

Using my implementation, which is to return a table of closures,

Right... I can read to:

http://www.lua.org/pil/16.4.html

In any case, I personally find all this circus to forcefully enforce encapsulation a total waste of time, personally that this. YMMV.

Cheers

--
PA
http://alt.textdrive.com/