Tuples provide a convenient way to bundle up values without having to define a class-based structure. Slang tuples are based on Scala tuples – the Slang parser just puts a few restrictions on how they can be used – so Slang’s syntax for tuples is identical to Scala’s.

Tuples are created using the syntax (element1, element2, …, elementn). Elements can be accessed from a tuple expression t (projected out of the tuple) using the syntax t._n where n is the position of the element to be accessed (using 1-based indexing). Tuple elements can have different types, and tuples can be nested. Tuple types have the form (T1,T2, …, Tn) where Ti is the type of the element at position i.

Slang supports both immutable and mutable tuples, but there is no syntactic via typing (e.g., in contrast to IS (immutable sequence) and MS (mutable sequence), see Chapter XXX). Instead, the mutability of a tuple is automatically detected and tracked by the Slang compiler.

Immutable Tuples

Here are some examples of working with immutable tuples. The Slang compiler detects that they are immutable because they have no mutable elements.

  val t1: (Z, B, String) = (0, F, "")             // immutable tuple has no mutable elements (mutability automatically detected)
  assert(t1._1 == 0 && t1._2 == F && t1._3 == "") // tuple element access: _N (Nth element, 1-based)
  val t2 = (t1, ("a", F), 1)                      // nested tuples
  assert(t2._1._2 == F)                           // accessing elements of nest tuples
  // t1._1 = 1                                    // ERROR: cannot assign to element of a tuple (in both Slang and Scala)

Mutable Tuples

Like Scala tuples, Slang tuples are value based – you can’t update the element values directly as you can with a mutable/var field of a Slang record. However, tuple elements can be mutable structures, and the structures themselves can be updated once they are projected from the tuple. The Slang compiler automatically detects when a tuple contains a mutable element. Such tuples are referred to as “mutable tuples” (this a misnomer such the tuple structure itself is not mutable – the element structures are).

Below is an example of working with Slang mutable tuples. The example illustrates the difference between trying to update the tuple value with a new element (disallowed) versus updating the contents of a tuple element (allowed for elements that are mutable). As with other mutable structures, Slang makes an implicit copy of mutable tuple values when they are assigned to variables/fields.

  val p1 = (1, MSZ(1))                            // mutable tuble (at least one mutable element)
  val p2 = p1                                     // implicit copy of p1's value to avoid aliasing
  assert(p1 == p2)                                // equal due to structural equality
  // p1._1 = 0                                    // ERROR: cannot update tuple value
  // p1._2 = MSZ(2,3)                             // ERROR: cannot update tuple value (even at a mutable element)
  p1._2(0) = 2                                    // can update content of a mutable element
  assert(p1 != p2)                                // pairs no longer equal due to update
  assert(p1._2(0) == 2)                           // access newly updated state
  assert(p2._2(0) == 1)                           // implicit copy preserved original value of MSZ

Pattern matching is commonly used to access elements of tuples (instead of the t._n projection notation above). See the following chapter for examples.