lua-users home
lua-l archive

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

This basically has to do with what is sometimes referred to as value
semantics v. object semantics and is an issue I've been worrying about to
some extent myself of late and again for a collection of 2-D geometry types
though I could also see it as relevant to complex numbers.

The distinction could be roughly summarized as being that for value types,
object identity doesn't matter. For objects, it does.

>From a practical standpoint, it means that "variables" hold values and for
value types we change the value held by the variable whereas for object
types we change the object referred to by the value of the variable.

The simple work around for this is to implement new value types as user data
-- though as noted in earlier discussions, doing this well also involves
worrying about how they behave as hash table keys. You then implement all
mutators as returning new objects.

One problem with this approach is that it is less "natural" than the value
semantics version. For example, a lot more people would probably be
comfortable writing:

    position.x = PinToGrid( position.x )

Than writing:

    position = postion:setX( PinToGrid( position.x ) )

Even without the direct assignment, you'd probably get lots of people
writing and then debugging:

    position:setX( PinToGrid( position.x ) )

That generates bugs that are probably easier to detect than the case of
using object-semantics for positions and having someone forget to do a copy,
but being the lesser of two evils doesn't make something good.

A second problem has to do with garbage. The straightforward implementations
of value semantics by having mutators return new objects can generate a fair
amount of garbage for temporary values. Generating garbage at a faster rate
increases the frequency with which one needs to perform garbage collection.
There are two potential fixes in this regard. One is some limited support
for reference counting so that temporaries get recycled quickly. The other
is something like a calculator construct where one could do things like:

    pointCalculator = point:makeCalculator();
    pointCalculator:subtractPoint( center );
    pointCalculator:scaleBy( 10 );
    pointCalculator:rotateBy( 2 );
    pointCalculator:addPoint( center );
    point = pointCalculator:getPoint();

This replaces 3 temporary objects with 1 temporary point calculator. One
could also implement these sort of semantics with a little less safety by
simply changing the metatable for the point:

    point = point:makeEditable();
        -- copies the point and changes the metatable
    point:subtractPoint( center );
    point:scaleBy( 10 );
    point:rotateBy( 2 );
    point:addPoint( center );
    point:freeze(); -- changes the metatable to remove mutation functions