lua-users home
lua-l archive

Re: lua-l Digest, Vol 29, Issue 56

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


Am 19.12.2012 01:26, schrieb Tomas Lundell:
On Wed, Dec 19, 2012 at 2:35 AM, <lua-l-request@lists.lua.org> wrote:
And everything because you want to write:
 map( filter( t, is_odd ), function( _, v ) print( v ) end )
instead of:
 for i,v in ipairs( t ) do
 if is_odd( i ) then
 print( v )
 end
 end
It's maybe a little silly to use a map for side effects - for that you'd
probably want to use a loop.
Why? Because map unfortunately constructs a superfluous table? Let's call the function 'each' like in underscore.js or its Lua equivalent[1] or Ruby (or table.foreachi like in previous Lua versions). If it's silly, it's not only me ...
 [1]: https://github.com/Yonaba/Moses/blob/master/docs/moses.md#each
Assuming you want to actually transform the
values in some way, say to square them, your example might look like this:
local new_table = {}
for i, v in ipairs(t) do
 if is_odd(i) then
 table.insert(new_table, v * v)
 end
end
I can't remember when I've used any of the table.* functions, but in principle, yes.
Which I would write like this:
 local odd_items = ifilter(is_odd, ipairs(t))
 local new_table = imap(function(i, v) return v * v end,
ipairs(odd_items))
Ok, you have the iterators variant of map/filter, at least for the input, but not the output. If I were to use map/filter, I would choose my version[2] with iterator input and output. The example would look like
 local new_t = {}
for _,w in map( function( i, v ) return v * v end, filter( is_odd, ipairs( t ) ) ) do
 new_t[ #new_t+1 ] = w
 end
No need for different map/imap, filter/ifilter variants, and constant memory overhead (two closures and one normal function) compared to Lua's plain generic for loop instead of linear overhead (temporary array + normal function) as in your example. So you are *nearly* as flexible (no break, only one key + one value, no numeric for, can't handle arrays with holes, etc.) and *nearly* as efficient as Lua's for loop with 4 additional public functions (2 in my case). And at first glance I can't even tell which version is shortest.
Note that all functions are flexible in that:
* You can choose whether you iterate using pairs or ipairs (or a custom
iterator)
* You can choose to return either a key-value table or an array (by
choosing map or imap)
/ Tom
Philipp
 [2]:
 do
 local function map_helper( fun, var_1, ... )
 if var_1 ~= nil then
 return var_1, fun( var_1, ... )
 end
 end
 function map( fun, f, s, var )
 return function( st, v )
 return map_helper( fun, f( st, v ) )
 end, s, var
 end
 end
 do
 local function filter_helper( pred, f, s, var_1, ... )
 if var_1 ~= nil then
 if pred( var_1, ... ) then
 return var_1, ...
 else
 return filter_helper( pred, f, s, f( s, var_1 ) )
 end
 end
 end
 function filter( pred, f, s, var )
 return function( st, v )
 return filter_helper( pred, f, st, f( st, v ) )
 end, s, var
 end
 end

AltStyle によって変換されたページ (->オリジナル) /