• 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 )

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

```