lua-users home
lua-l archive

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


Quoting Dirk Laurie (2016-07-22 10:48:09)
> 2016-07-22 4:57 GMT+02:00 Patrick Donnelly <batrick@batbytes.com>:
> > For some slightly early "It's Friday" discussion, what do you use the
> > __call metamethod for? Discuss your favorite hacks, strange problems
> > solved, code golf hole-in-ones, etc.
> >
> > To get discussion started, I'll leave this here:
> >
> > t = setmetatable({}, {__index = table, __call = function(t, method)
> > return function(...) t[method](t, ...) end end}) -- create a method
> > binding
> > string.gsub("foo", ".", t "insert")
> > for k,v in pairs(t) do print(k,v) end --> 1 f \n 2 o \n 3 o \n
> 
> I use a minimal object-oriented paradigm in which the method
> table is also the __index and the constructor.
> 
> local init = function(class,object)
>   setmetatable(object,class)
>   return object
> end
> 
> local Class = function(methods,typename)
>   methods.__index = methods
>   methods.type = function() return typename end
>   return setmetatable(methods,{__call = init})
> end
> 
> I don't package these in a module. They are clearly visible to
> whoever reads the listing.
> 
> After that, e.g.
> 
> Data = Class({},'data')
> data = Data{}
> 
> I've been using this for so long that I have forgotten where I got it.
> Probably from PiL.

I do something similar to allow “instantiation” of objects with the __call
metamethod, to have Python-like syntax. I do it manually every time, without
having any helper functions. It goes like this.

  local Point = {}
  Point.__index = Point

  setmetatable(Point, { __call = function (self, x, y)
    return setmetatable({ x=x, y=y }, self)
  end })

  -- Metamethods can be attached directly
  function Point:__tostring()
    return string.format("Point(%d, %d)", self.x, self.y)
  end

  function Point:translate(dx, dy)
    self.x, self.y = self.x + dx, self.y + dy
    return self
  end

...and so on. Probably I do not use helper functions because I just see this
as “needed boilerplate”, and also because it's not too long it feels right to
write this explicitly. I cannot remember from where I got this... it could
have been as well that my code slowly morphed over time to arrive to this
pattern, which has been unchanged for the last 5 years at least.

Sometimes I have used __call for other purposes, but not very often. Most of
the time to return custom iterators:

  local obj = Cls()  -- This has a __call metamethod...
  for x in obj() do  -- ...which returns a coroutine.
    print(x)
  end

Cheers,

--
 ☛ Adrián

Attachment: signature.asc
Description: signature