Log In  


One of the simple examples in the LUA documentation for metamethods is to implement set logic on tables.
s1+s2 returns a new set that is the union of the two by defining __add, s1*s2 returns the intersection thanks to __mul, so far so good.
There is also the very useful __index and __newindex to handle reads and writes to unassigned indexes of the table, but the very important assignation metamethod at table level seem to silently not exist, as if it were of no use.

when I do
set1=set2
followed by
set2=set2+{new_elem}

I most certainly didn't mean for set1 to be changed.

There's of course plenty ow ways to force the behavior I wanted :
set1=set2+{}
would work.
We could define a set_copy function
set1=set_copy(s2)

But there seem to be no way to override the assignation behavior, like we would redefine the = operator of a class in C++ for example.

Could someone please shed some light on the subject ? What is the reason behind this omission ?
Is there a way to override table assignation that I missed, or maybe a conventional good us of copying objects by value, for objects where it makes more sense ?



If you could change the assignment operator for tables, it would complicate a lot of things. For instance, how would function arguments work? arguments are local to the function that's being called, so they'd get assigned the value of the inputs. This would complicate functions that mutate tables. Unless there would be an override so that function arguments are always passed by reference?

I can think of some other reasons, but they have workarounds so they're not really valid.

Also, funny thing, strings are actually passed by reference, there's just nothing that mutates them (there can also only ever be 1 string with a certain value at any time)


I don't know the answer to your question, but for some 3D vector routines I implemented __add etc to create and return a brand new table.

vec={}
vec.new=function(x,y,z)
 local v={x,y,z}
 setmetatable(v,vec)
 return v
end
vec.__add=function(a,b)
 local v={a[1]+b[1],a[2]+b[2],a[3]+b[3]}
 setmetatable(v,vec)
 return v
end

This means:

v2=vec.new(1,2,3);
v2=v1
v2=v2+vec.new(4,5,6);

Will leave v1 set to [1,2,3], for example.

Essentially it treats each table as immutable.


the reason is that assignment is a fundamental part of the language, not an operation that a type can override!

when we do target=player1, or level.target=players[1], or world["target"]=level.target, we are assigning variables, or names, to point to the same table object. changing one changes all of them, because these are not separate objects, or values, but only names pointing to the same table.

high-level languages like lua or python work this way. it is quite different from C and similar languages, where a variable is a thing in itself, and concepts like references and values exist.



[Please log in to post a comment]