lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Wed, Nov 28, 2018 at 4:06 AM Egor Skriptunoff
<egor.skriptunoff@gmail.com> wrote:
>
> On Tue, Nov 27, 2018 at 1:31 AM Coda Highland wrote:
>>
>> >>>> Lua has little to no support for composition-based OOP
>> >>> Can you give an example of what you would want here?
>> >> The classic Cratera[1] `foo:[component].method()` (note the colon) syntax.
>> > What OOP languages do support this "composition-based OOP" ?
>>
>> Lots of them. C++, Java, C#, Python...
>>
>> Python's the only one I know of off the top of my head
>> that can make it look that clean.
>
>
> How does Python support "composition OOP"?
> Do you mean the ability to define __getattr__?
> It doesn't look like a "support"; a user has to do all the work manually.
> It' very similar to Lua's ability to define __index.

As I said in another post, by default you don't explicitly call out
the component you want to use. Python accomplishes composition via
multiple inheritance ("mixins"), so you'd just write a.c() instead of
a.b.c().

But you're right, being able to tinker with Python's metaclass
functionality is how Python is able to achieve something analogous to
the specific technique under discussion. And yes, it IS like being
able to define __index, except since Python has a native notion of
classes there's a different attitude about doing so.

> I like the suggestion to make "a:b.c()" a valid Lua syntax.
>
> But the next question from Sony L. would be the following:
> How to save intermediate value in this code
> a:b.c()
> a:b.d()
> to rewrite it in optimized way
> local x = a:b
> x.c()
> x.d()

(Nitpick: it would have to be x:c(), not x.c().)

I hinted at the same notion earlier. The problem with doing this at
all is that it's EXPENSIVE -- probably more expensive than just
evaluating the two paths in the first place. You have to allocate an
object to represent the binding, such that using . or : to access its
contents returns b, but using () passes through a. And then you have
to make the function call machinery detect when one of these objects
is being used in order to make sure the right value is passed in the
parameter list. And of course, this allocation will subsequently need
to be garbage-collected... It's really not worth it, especially since
this overhead would apply to ALL uses of : and ALL uses of () even if
it's not needed unless you add EVEN MORE complexity to the parser.

In practice it would be better to write this:

local x = a.b
x.c(a)
x.d(a)

This works with stock Lua or with the proposed a:b.c() syntax patch
and doesn't involve any additional allocations.

/s/ Adam