Skip to content
Artūras Šlajus edited this page Oct 28, 2016 · 1 revision

Overview

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.

Usage

Creation

// 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.

Adding items to tuple

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');

Drawbacks

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));