I'm trying to do some functional programming techniques on lists in D, and while I'm happy that there's some functionality to be found, some of (what I perceive as) the language's foibles don't make it as smooth as I'd like. Here's an example:

import std.stdio, std.algorithm;

void main() {
        string[][] example = [["a", "b", "sdflk"],
                                           ["sdflkjsd", "sdl"],
                                           ["sdfjhsdklfjh", "sdkjfh", 
"alskaslk"]];
        writeln(example);
        int i=2;
        bool isLongEnough (string[] slist) {return slist.length > i;}
        example = filter!(isLongEnough)(example);
        writeln(example);
}

It seems a perfectly valid desire, to have an array and want to prune it down into an array that satisfies certain requirements. After all, this is exactly what filter is supposed to do. This code seems fairly straightforward then, but trying to compile it:

dmd test.d
test.d(10): Error: cannot implicitly convert expression (filter(reps)) of type FilterResult!(isLongEnough, string[][]) to string[][]

So essentially, the compiler is telling me that even though filter's whole raison d'etre is to take a data structure and return the same kind of data structure, but with some values possibly removed, it not only returns a weird in-house-brand "FilterResult" type, it can't even convert this into a into a string[][] type. Now, I could use "auto" instead of "string[][]", and it works, but I have no use for a "FilterResult". I don't know what methods I can call on it, or what it's made out of. I want a string[][].

A similar story happens with the map function. Map takes an array and a function and returns another array which is of values computed from applying the function to the input array. One would think, then that this code would work:

void main() {
        string[][] reps = [["a", "b", "sdflk"],
                                           ["sdflkjsd", "sdl"],
                                           ["sdfjhsdklfjh", "sdkjfh", 
"alskaslk"]];
        writeln(reps);
        int[] lengths = map!("a.length")(reps);
        writeln(lengths);
}

After all, the .length function returns an int, and we have an array of them, so map returns an int, right? Wrong!

dmd test.d
test.d(8): Error: cannot implicitly convert expression (map(reps)) of type MapResult!(unaryFun, string[][]) to int[]

Once again, even though the returned array is, for all intents and purposes, an int[], I can't call it that. Which means I can't concatenate onto an existing int[], for example.

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?

Reply via email to