Filter and Map's weird return types cause frustration...

Peter Alexander peter.alexander.au at gmail.com
Sat Feb 23 02:14:17 PST 2013


On Saturday, 23 February 2013 at 08:48:25 UTC, Allen Nelson wrote:
> Why are filter and map returning these weird one-off types in 
> the first place? Why would filter return anything but the same 
> type of list that it was passed as an argument? Why would map 
> return anything other than an array of whatever type matches 
> the return value of the operator? And if there's some good 
> reason why these things are the case, why then at the very 
> least would you not be able to easily cast the return type into 
> the return type that you want?

If you are using an array, you can construct an array from the 
result using std.array.array

int[] evens = [1, 2, 3, 4, 5].map!(x => 2*x)().array();

The reason map, filter, and most other range functions don't 
return the same type of array is because they are lazy. For 
example:

int[] twoFourSix = [1, 2, 3, 4, 5].map!(x => 
2*x)().take(3).array();

Here, the mapping function is only called on the first three 
elements of the array. If map returned the array [2, 4, 6, 8, 10] 
then it would be doing more work than necessary since the take 
only cares about the first 3 elements.

Also consider infinite ranges:

auto twoFourSixAdInfinitum = cycle([1, 2, 3]).map!(x => 2*x)();

What should map return here? You cannot have infinitely sized 
arrays!

There's no way to have map return the same range as the input, or 
even just an array, while also being lazy. If you want an array, 
use std.array.array().

Haskell manages to get around this by adding an extra layer of 
indirection around every operation, which hurts performance. D's 
standard library is designed to be high performance by default, 
which unfortunately does hurt expressiveness a little bit.


More information about the Digitalmars-d mailing list