enumerate, and some improvements
bearophile via Digitalmars-d
digitalmars-d at puremagic.com
Wed Sep 24 04:32:02 PDT 2014
Jakob Ovrum and others have added an enumerate() function to
Phobos:
https://issues.dlang.org/show_bug.cgi?id=5550
https://github.com/D-Programming-Language/phobos/pull/1866
A problem with enumerate() (present in other ranges too):
void main() {
import std.stdio, std.range;
auto A = [0, 0, 0, 0];
// A trap: the compiler here accepts ref but it's ignored.
foreach (immutable i, ref x; A.enumerate)
x = i;
writeln(A);
}
Outputs:
[0, 0, 0, 0]
------------------
A feature I'd like in Phobos is an optional "key" function for
the min/max functions. An example, compared to using "minPos"
(https://d.puremagic.com/issues/show_bug.cgi?id=4705 ):
void main() {
import std.stdio, std.algorithm, std.range;
string[] data = ["red", "hello", "yes", "no", "roger", "bud"];
data
.minPos!q{ a.walkLength > b.walkLength }
.front
.writeln;
// Proposed:
data.reduce!(max!q{ a.walkLength }).writeln;
}
The optional key function for max/min functions has some
advantages: the code is simpler, shorter, and it computes
walkLength only once for each string (so it's faster if the key
function is nontrivial and gives less surprises if the given
range is not pure).
------------------
A range I'd like in Phobos is std.range.pairwise:
https://d.puremagic.com/issues/show_bug.cgi?id=6788
It's different from cartesianProduct and zip, it generates just a
triangle of pairs:
void main() {
import std.stdio, std.typecons;
auto data = [1, 2, 3, 4];
foreach (tup; data.pairwise)
writeln(tup);
foreach (i, x1; data)
foreach (x2; data[i + 1 .. $])
writeln(tuple(x1, x2));
}
It should print:
Tuple!(int, int)(1, 2)
Tuple!(int, int)(1, 3)
Tuple!(int, int)(1, 4)
Tuple!(int, int)(2, 3)
Tuple!(int, int)(2, 4)
Tuple!(int, int)(3, 4)
So:
foreach (tup; data.pairwise)
is similar to:
foreach (i, x1; data)
foreach (x2; data[i + 1 .. $])
auto tup = tuple(x1, x2)
Such nested iteration is a common need.
------------------
I'd like "zip" to optionally accept a function/constructor:
https://d.puremagic.com/issues/show_bug.cgi?id=8715
Two usage examples:
void main() {
import std.range;
auto r1 = zip!q{a + b}([1,2,3], [10,20,30]);
static struct Vec { int x, y; }
auto r2 = zip!Vec([1,2,3], [10,20,30]);
}
This can be done with zip+map but this is shorter and more
efficient. It's similar to the Haskell function zipWith.
------------------
And I'd like map/filter to accept arrays and associative arrays,
and not just functions:
void main() {
import std.algorithm: map;
auto keys = [1, 2, 1, 1, 1];
auto a = [0, 10, 20];
auto r1 = map!(k => a[k])(keys); // OK
auto r2 = map!a(keys); // Error
auto aa = [1: 10, 2: 20];
auto r3 = map!(k => aa[k])(keys); // OK
auto r4 = map!aa(keys); // Error
}
This is a common idiom in Clojure. Arrays and associative arrays
can be seen as functions defined by an enumeration of
input-outputs.
Bye,
bearophile
More information about the Digitalmars-d
mailing list