lua-users home
lua-l archive

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

> The for loop iterators are often ideal uses of coroutines, instead of
> vnext we can write vpairs so it returns a coroutine (er, a wrapped
> coroutine):

> function vpairs(table, value)
>   return coroutine.wrap(
>     function ()
>       for k,v in table do
>         if v == value then
>           coroutine.yield(k, v)
>       end
>     end
>   end
>   )
> end

> A classic use of coroutines.  Or maybe I've been using too much Icon.

Perhaps :)

This is actually easier and faster with the walker pattern:

function vforeach(table, value, fn)
  for k, v in table
    if v == value then
      local rv = fn(k, v)
      if rv then return rv end

Walked iteration blocks can be composed in a more or less convenient way; 
the above could be generated as well with:

function ifle(value, fn)
  return function(k, v)
    if value <= v then return fn(k, v) end

function ifgt(value, fn)
  return function(k, v)
    if value > v then return fn(k, v) end

-- eg:

> t = {bob = 2, joe = 4, kate = 6, elmer = 8}
> table.foreach(t, ifle(3, ifgt(7, print)))
joe     4
kate    6

In this sense, it would actually have been interesting if the extended-for 
statement just gave the iterator function the iteration block as an 
argument; the interfaces would be slightly simpler, and there is little 
semantic difference.

Where coroutines are useful is for the case where the iteration block 
wants to retain state, something which cannot easily be done either with 
walkers or with iterators.