lua-users home
lua-l archive

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

Todd Berkebile <> dixit:

> local a = 10
> local b = a   -- 'b' is a new number with the same value as 'a'
> b = b + 1     -- this only changes 'b', not 'a', because its a copy
> Normal tables work the same way:
> local a = { member=10 }
> local b = a.member -- again 'b' is a copy, not a reference
> b = 5  -- only 'b' is modified, not 'a'

Your reasoning is wrong here, the // is false. In the second case b is not assigned to a, but to a member. If you change your test case with "b = a" instead, then you'll see b is only a reference to the same object/table as a is pointing to: changing member on b will change it for a as well.

[Personal, half-OT, views follow]

The case of numbers (and of strings in Lua, and depending on the language of other builtin types) is special for they are "immutable". This means one cannot *modify* a number, only *replace* it. Unlike a table (and numerous other types in other languages). The following tree view may help you?

assignment can actually perform:
   creation             x = a   -- if x does not yet exist in reachable scope
   change               x = a   -- if x already exists
      replacement       x = 1   -- cause immutable type
      modification      x.m = 1 -- in Lua, only for a table

The last case is not possible for an object of an immutable type. So, immutable objects cannot really act as genuine objects (with an identity); if fact, they act as value, meaning each is a piece of information (of data) on current state (global state or state of a real object).

Conversely, Lua tables can only act as real objects, even if semantically, in the model you're expressing, they represent values (pieces of data) in fact. A value may happen to be compound, so need to be implemented as a table. This can be confusing and sometimes requires attention:

   pos = {x=1, y=1}               -- compound value
   point1 = {pos, color="#fff"}   -- real object
   -- But both are objects in Lua.

   -- point2 happens to start at same pos, this is program logic
   point2 = {pos=point1.pos, color="#000"}

   -- depending on method move's actual code, this may move point1, too!
   point2.move(dx, dy)

To avoid the issue at the root, we effectively need a distinction between real objects and pure values, a distinction that does not exist in common languages. To replace the "implementation detail" distinction between mutable & immutable types by a conceptual one.

Note that a converse trap happens when a conceptual object is implemented as an immutable type, which may happen in Lua if it requires only a single piece of data to be fully defined, eg a point in 1-dimensional space.

   points = {p1=1, p2=2, p3=3}
   -- this will not move p1,p2,p3, for they're immutable,
   -- so a brand new object is silently created
   for _,point in pairs(points) do
       point = point + d
   -- we need to explicitely reassign the new object,
   -- as if they were values instead
   for key,point in pairs(points) do
       points[key] = point + d

The latter would be conceptually correct if we were iterating over _positions_ (values), not points (objects).

* A syntactic distinction between both natures of data: to say whether one piece of data is to be considered as object (with identity and referenced), or value (describing a quality of some thing).
* A difference in assignments of the form "x=y": in case y is an object, only its reference is passed by; in case of a value, a copy is performed.
* An implementation scheme: look for "value object" design pattern. This implements the trick that a value change always performs & return a copy, instead of changing the value on place. So, you'd always have to write eg:
   pos = pos.change(...)
instead of:

I guess there is an interesting track to be explored (for a new language). As a last example at a meta level, funcs are objects, sure, even if they cannot be modified in code in most languages -- so the mutable/immutable distinction does not even apply.


la vita e estrany