lua-users home
lua-l archive

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


On Sun, Dec 16, 2012 at 10:39 PM, Dirk Laurie <dirk.laurie@gmail.com> wrote:
> 2012/12/16 Coda Highland <chighland@gmail.com>:
>>
>>> I interpret setEnabled() as "set as enabled", while being the same as
>>> setEnabled(nil).
>>
>> Ah, and that's where we differ -- I read "setEnabled(" as "set the
>> enabled property to", and thereby get an incomplete sentence if there
>> isn't a parameter inside.
>>
>
> That's why one should not have hundreds of tiny routines with names
> like that. `option{Enabled=true}` is unambiguous, extensible and uses
> up only one name. PiL 5.3.
>
> I've never been able to understand why people are willing to swallow
> great gulps of pseudo-Java in order to avoid creating one table. Even
> a well-respected member of the Lua community, in another thread,
> recoiled in horror at the construction `{...}`.
>

It's more than just the creation of one table. It's also the
absolutely ugly implementation that would be necessary to IMPLEMENT
that function -- you're still incurring the overhead of resolving and
invoking a function, and THEN you're hashing up your own function
resolution and dispatch mechanism INSIDE that function that can't be
cached.

It seems to me that I could choose:

function setEnabled(on) ... end
function isEnabled() ... end

function setFoo(bar) ... end
function foo() ... end

Or I could choose:

local propertySetters = {
  enabled = function(on) ... end,
  foo = function(bar) ... end
}
local propertyGetters = {
  enabled = function() ... end,
  foo = function() ... end
}

function set(key, value)
  propertySetters[key](value)
end

function get(key)
  return propertyGetters[key]()
end

Or I could choose, using the same propertyGetters/Setters tables:

function set(tbl)
  for key, value in pairs(tbl) then
    propertySetters[key](value)
  end
end

function get(key) --[[ same as above ]] end

This last one has the unpleasant fact that the getter and setter are
asymmetric -- set takes a table with the property names as keys, get
takes either a single string property name or, if you're a little
fancier, a table containing the property names as values; either way
the getter needs quotes and the setter doesn't.

You can resolve that ugliness by using __newindex and __index to
simulate properties, which is probably the most consistent behavior
among the options besides the "Java"-style one.

Of course, if you're using this scheme, you're defining JUST AS MANY
functions to define a property as the "Java" style, plus two more, and
you're getting at least twice as much function-call overhead. While
this may not matter for a single property, when ALL of your properties
are running through this kind of function it very well might add up.
(Or it might not; I understand premature optimization is bad.) And
worse, the table-accepting version means you can't have setters that
accept multiple parameters.

So ultimately, using "Java"-style properties consistently means you
get a consistent API and minimum overhead. It's no less readable to
new users than any of the other solutions (and more consistent than
some). I'm not saying it's the only solution -- implementing
properties with metamethods is essentially just as good and allows you
to skip on the function definitions for setters that don't need any
logic.

TL;DR: Don't bash on the "Java"-style properties; they're not bad.

/s/ Adam