lua-users home
lua-l archive

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

On 20 Nov 2010, at 16:35, Lorenzo Donati wrote:
All this is a bit cumbersome, because for every new "value class" you need a new specialized "container".

You can just replace 'vec_key.repr' by something like 'getmetatable(vec_key):__hash()'. For an example, take a look at:

Therefore I'd find useful a metamethod which, if present on the item being used as key, could be used to retrieve the actual key used for hashing.
But I realize that that maybe this check on every access for every key could be a big performance hit.

Yes, besides the probable performance and complexity overhead in the majority of uses of Lua tables where such thing is not needed, such feature is only one possible solution for this problem of using complex objects as a key of a map, not necessarily the best one. So maybe it is better to let the programmer implement the best solution himself (or use a third-party library) when necessary.

That's why I asked: I expected that someone could say I proposed something silly, but being criticized constructively is a good way to learn faster :-).

Have you searched the list archives for '__hash'?

I'm discovering day by day that I have to unlearn so much! :-)

I don't know what you mean by "unlearn", but it is always nice to learn new ways of solving old problems. In your example, consider using internalized tuples[1], for example:

 local tuple = require "tuple"
 local tuple_index = tuple.index -- faster than 'tuple.create'

 local Vec_MT = {}
 Vec_MT.__index = Vec_MT

 -- memoize table to internalize 'vectors'
 local tuple2vector = setmetatable({}, {
 	__mode = "v",
 	__index = function(self, tuple)
 		local x, y = tuple()
 		local vector = setmetatable({ x=x, y=y }, Vec_MT)
 		rawset(self, tuple, vector)
 		return vector

 -- very simple 2D vector object constructor
 local function Vec(x, y)
 	return tuple2vector[ tuple_index[x][y] ]

 function Vec_MT:__add(v)
 	return Vec(v.x + self.x, v.y + self.y)

 -- let's exercise our "class"
 local v1, v2, v3 = Vec(1,2), Vec(1,2), Vec(2,4)
 assert( rawequal(v1, v2) )
 assert( not rawequal(v1, v3) )
 assert( v1 == v2 )
 assert( v1 ~= v3 )

 -- now we want to put Vec objects in a table as keys
 local v_set = { [v1] = true, [v2] = true, [v3] = true }
 assert(v_set[Vec(1,2)] == true)
 assert(v_set[v1 + v2] == true)
 assert(v_set[v1 + v3] == nil)


Renato Maia
Computer Scientist