[Issue 7957] New: std.functional untuple/untupleReversed too
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Fri Apr 20 18:07:37 PDT 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7957
Summary: std.functional untuple/untupleReversed too
Product: D
Version: D2
Platform: All
OS/Version: All
Status: NEW
Severity: enhancement
Priority: P2
Component: Phobos
AssignedTo: nobody at puremagic.com
ReportedBy: bearophile_hugs at eml.cc
--- Comment #0 from bearophile_hugs at eml.cc 2012-04-20 18:08:34 PDT ---
I suggest two functions like this in Phobos. Maybe a more correct name for them
is apply/applyReversed, but apply() is probably meant to be more flexible.
The purpose of untuple is to apply the items of a tuple as arguments to a
function, inside map/filter. So instead of this:
t => foo2(t.tupleof)
You write a less complex:
untuple!foo2
Python has the itertools.starmap function to perform a lazy map with untuple
(apply) too, but it lacks a starfilter:
http://docs.python.org/library/itertools.html#itertools.starmap
untupleReversed does a little more, because it also reverses the tuple items
before feeding them to the foo2 function. This is often useful for 2-tuples,
it's related to (but not the same as) the "flip" function used in Haskell:
-- | @'flip' f@ takes its (first) two arguments in the reverse order of @f at .
flip :: (a -> b -> c) -> b -> a -> c
flip f x y = f y x
It's an "adapter" between a range of tuples and an already written function
that takes flipped or reversed arguments.
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
import std.algorithm, std.range, std.stdio, std.functional,
std.typecons, std.traits;
// To apply a given callable to a Tuple (alternative name: "apply").
template untuple(alias callable) {
auto untuple(Tup)(Tup t)
if (isTuple!Tup && ParameterTypeTuple!callable.length == Tup.length) {
return callable(t.tupleof);
}
}
void main() {
auto a1 = "abcd"d;
auto a2 = [10, 20, 30, 40];
auto a3 = [100, 200, 300, 400];
static int foo2(dchar a, int b) { return a + b; }
zip(a1, a2).map!(t => foo2(t.tupleof))().writeln();
zip(a1, a2).map!(untuple!foo2)().writeln();
static int foo3(dchar a, int b, int c) { return a + b + c; }
zip(a1, a2, a3).map!(untuple!foo3)().writeln();
}
Output:
[107, 118, 129, 140]
[107, 118, 129, 140]
[207, 318, 429, 540]
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
One version that also reverses the tuple items:
import std.algorithm, std.range, std.stdio, std.typecons, std.traits,
std.typetuple, std.string, std.conv;
// _genIndexes("foo", 3) ==> "foo[2], foo[1], foo[0]"
private string _genIndexes(string name, size_t start) {
string[] result;
for (int i = start - 1; i >= 0; i--)
result ~= name ~ "[" ~ text(i) ~ "]";
return result.join(", ");
}
// To apply a given callable to a Tuple (alternative name: "apply"),
// but flipping the tuple items.
template untupleReversed(alias callable) {
auto untupleReversed(Tup)(Tup t)
if (isTuple!Tup && ParameterTypeTuple!callable.length == Tup.length) {
mixin("return callable(" ~ _genIndexes("t", Tup.length) ~ ");");
}
}
void main() {
auto pairs = zip([10, 20, 30, 40], [100, 200, 300, 400]);
static int div2(int a, int b) { return a / b; }
pairs.map!(t => div2(t[1], t[0]))().writeln();
pairs.map!(untupleReversed!div2)().writeln();
}
Output:
[10, 10, 10, 10]
[10, 10, 10, 10]
--
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
More information about the Digitalmars-d-bugs
mailing list