lua-users home
lua-l archive

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


A lollipop is a kind of sugar that is specially designed to suck.

C++ is full of it. Python is full of it. Ruby is full of it. Perl has
nothing but.  Even C cannot be excused (you_agree? great : get_stuffed).

Lua does not have much.

-  `table.name` for `table["name"]` is not a lollipop: it is compact
    as well as intuitive.

-   `object:method(x,y)` for `object.method(object,x,y)` is not
    a lollipop when used as a function call: it allows chained
    invocation avoiding short-lived local variables.

But there are two kinds of sugar I find myself using less and less.
When I do (usually while debugging), I kick myself.

Both deal with function definition.

Object-oriented definition
--------------------------

You think it looks like the call. So it does, but it hides too much.

    function prototype:func(x,y)
       -- self, self, self, self, ...
    end

This is only convenient if you write objects that have only one instance
(in which case why bother?)  Otherwise you don't want the methods in
the object among the instance-dependent fields; they should go into
a method table accessed via the `__index` metamethod, which normally
is not a function but simply the method table itself.

`object:func(x,y)` is invariably used to mean `object["func"](object,x,y),
never `rawget(object)(object,x,y)`. The latter is what you are going to
get, though, if you forget

    getmetatable(object).__newindex={}

before unwrapping the lollipop. In which case you must not forget

    getmetatable(object).__index = getmetatable(object).__newindex
    getmetatable(object).__newindex=nil

when you're done, otherwise all the fields of the object will also
go into the method table.

Much more readable is to make the method table explicit.

    object_method={}
    object_method.func(object,x,y) = ...

None of this self, self, self (which even Python does not inflict
on you, even if most Python programmers do it regardless). You can,
earlier or later, even just in time, decide whether your
object-oriented style requires your methods in the metatable
itself or in its `__index`.

Any function definition with 'function' before the name
-------------------------------------------------------

How many characters do you save?

    local function func(x,y)
    local func=function(x,y)

Zero. That's right, nada, nichts, rien, zilch.

So why push the name 'func' even further from the left margin?

Moreover, you may need a forward definition occasionally.

    local func, another_func

    another_func = function
      -- that refers to 'func'
    end

    func=function(x,y)
      -- which refers to 'another_func'
    end

In which case the lollipop is available for `another_func` but
not for `func`. Why submit to such asymmetry?

Recognize these lollipops for what they are: atavistic remnants
of some non-Lua language that crept into the design at a stage
when it seemed like a good idea. Recognize them, but don't use them.
Your programs will read better and require less debugging.