lua-users home
lua-l archive

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


I just posted a little patch and some explanatory material to
<http://lua-users.org/wiki/ExtendingForAndNext>.

Summary: The patch adds a "next" tag method which allows the definition of
iteratable userdata (or tables iteratable in a non-default manner) as well
as the possibility to defined generator functions with a consistent syntax.

An example of the second:

function words(str)
  return
    function(k)
      local _, k, v = strfind(%str, "([%w]+)", (k or 0) + 1)
      return k,v
    end
end

-- Some uses:

function count(gen)
  local c = 0
  for k, v in gen do c = c + 1 end
  return c
end

function dictionary(gen)
  local dict = {}
  for k, v in gen do dict[v] = (dict[v] or 0) + 1 end
  return dict
end

function tovector(gen)
  local vec = {n = 0}
  for k, v in gen do tinsert(vec, v) end
  return vec
end

--- Two tag method examples:

VECTOR_TAG = newtag()
settagmethod(VECTOR_TAG, "next",
                         function(v, i)
                           i = (i or 0) + 1
                           if i <= v.n then
                             return i, v[i]
                           end
                         end)

-- use the tag method:

-- (see above)
wordlist = tovector(words(str))
settag(wordlist, VECTOR_TAG)

for i, v in wordlist do
  -- something; i is the numeric indices and v the successive values
end

-- Here's a possibly more interesting example. A Queue is often
-- useful for holding pending tasks. This implementation provides
-- the standard functions but it also provides an iteration method
-- The iteration method is destructive; when you're handed
-- a queue element, it's already been removed from the queue.
-- You can put new things on the queue during the
-- iteration, and they will eventually be iterated over; the
-- iteration ends when the queue is empty.
-- This is not a particularly efficient implementation; I
-- was trying to keep it simple to be illustrative

QUEUE_TAG = newtag()

function qmake() return settag({low = 1, high = 0}, QUEUE_TAG) end

function qget(q)
  local low, v = q.low, nil
  if low <= q.high then
    v, q.low = q[low], low+1
    return v
  end
end

function qput(q, thing)
  q.high = q.high + 1
  q[q.high] = thing
end

function qisempty(q) return q.low > q.high end

settagmethod(QUEUE_TAG, "next",
             function(self) return not qisempty(self), qget(self) end)



Oxfam works with others to find lasting solutions to poverty and suffering.

Oxfam GB is a member of Oxfam International, a company limited by guarantee and registered in England No. 612172.
Registered office: 274 Banbury Road, Oxford OX2 7DZ.
Registered charity No. 202918.

Visit the web site at http://www.oxfam.org.uk