  lua-l archive

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

• Subject: Re: table.copy
• From: RLake@...
• Date: Thu, 26 Jun 2003 15:18:58 -0500

```> 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
end
end
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
end
end

function ifgt(value, fn)
return function(k, v)
if value > v then return fn(k, v) end
end
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.

```