[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: lua-l Digest, Vol 29, Issue 56
- From: Philipp Janda <siffiejoe@...>
- Date: Wed, 19 Dec 2012 03:10:34 +0100
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