Tuples
Artūras Šlajus edited this page Oct 28, 2016
·
1 revision
Tuples are generic data containers for grouping fixed-length data of different types into one object. There are tuples defined in tlplib from 1 element to 22 elements. If you need a tuple with more than 22 fields, you probably want to use a Data Struct.
// Type is Tpl<int, string, char>
var tuple = F.t(3, "foo", 'c');
You can use the constructor as well, but avoid that, because of Boilerplate.
// We specify the types twice - first as constructor type arguments and then we
// know the types from the actual parameters we pass to the constructor.
var tuple = new Tpl<int, string, char>(3, "foo", 'c');
Usually they are used when you want to return multiple values from a method, but no specific type is needed.
public static IEnumerable<Tpl<A, int>> zipWithIndex<A>(this IEnumerable<A> enumerable) {
var idx = 0;
foreach (var a in enumerable) {
yield return F.t(a, idx);
idx += 1;
}
}
Here there is not much point in having a separate data type, so we use a tuple to package two values together.
You can also append or prepend items to tuples.
var t2 = F.t(1, "foo");
// Tpl<int, string, char> t3a => (1, "foo", 'c')
var t3a = t2.add('c');
// Tpl<char, int, string> t3b => ('c', 1, "foo")
var t3b = t2.unshift('c');
Fields in tuples are not named. You can create a Data Struct if you want explicit names or you can destructure them manually.
public static void workOnTuple1(string name, Tpl<int, string> t) {
// This takes one line per tuple field to destructure.
var count = t._1;
var type = t._2;
otherMethod(name, count, type);
}
public static void workOnTuple2(string name, Tpl<int, string> t) =>
// Only one line, but will create a closure containing `name`.
t.ua((count, type) => otherMethod(name, count, type));
public static void workOnTuple3(Tpl<int, string> t) =>
// This is fine though, no closure allocated.
t.ua((count, type) => otherMethod("some constant name", count, type));