lua-users home
lua-l archive

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


On Fri, Sep 11, 2009 at 4:19 AM, John Hind <john.hind@zen.co.uk> wrote:
> But how would you have a generalised name that would be appropriate in
> diverse cases? If there was only one iterator, this would work, call it
> something generic like "iter", but if you have two (as at present) you need
> to distinguish them by function and this raises the question, why not three
> or four? The other problem is that it is the name of the library function
> ("pairs" or "ipairs") that the "user" sees, not the name of the
> corresponding (proposed) metamethods.
>
> On the "__iter" proposal this would work exactly like the "__call" trick
> except that "__iter" would apply in the context of generic for only, while
> "__call" would continue to apply in all other cases. So you would be able to
> pass parameters to the iterator (more formally the "iterator factory") just
> as you can now with the "__call" trick.
>
> It is important to realise that the "__pairs" and "__ipairs" proposal is not
> just the "__iter" proposal with a different name. The latter requires core
> language changes while the former is a very shallow and minor change which
> effects only the "pairs" and "ipairs" functions in the base library - they
> would delegate to the like-named metamethods if present or do what they do
> now if not. This is similar to the way the "__tostring" metamethod works
> with the "print" library function.

As John Hind suggested above, it seems that __iter metamethod is the
most sensible solution here. The __iter metamethod would be the
"fallback" for the expected function in the generic for explist. We
expect most metamethods to work as fallbacks but __pairs and __ipairs
instead define the behavior of those functions, not how Lua should
fallback when trying to iterate over the given object.

pairs and ipairs would still be useful with this __iter metamethod as
tables have no __iter metamethod by default (naturally). We can also
set the __iter metamethod of our metatables to next or (ipairs{}) to
alleviate the need for calling pairs or ipairs manually.

As noted earlier, this frees up __call for its (apparent) intended purpose.

Finally, it is very easy now to setup an iterator for a proxy table
that correctly iterates over our "hidden" table without exposing the
hidden table (sandboxing). As an example:

local read_only (t)
  return setmetatable({}, {
    __index = t,
    __newindex = function (t, k, v)
      error("attempt to modify a read-only table", 2);
    end,
    __iter = function (proxy, key)
      return next(t, key);
    end
    __metatable = {},
  });
end


-- 
-Patrick Donnelly

"Let all men know thee, but no man know thee thoroughly: Men freely
ford that see the shallows."

- Benjamin Franklin