Scala - Pattern Matching on Tuple



Tuples in Scala are used in pattern matching. These decompose their elements and handle them expressively. Extending tuples with the Matchable trait for safe pattern matching.

The syntax is as follows -

Syntax

tuple match {
  // pattern matching logic
  case (element1, element2, ...) =>
  // default case
  case _ =>
}

Basic Tuple Patterns

You can match basic tuples by their structure and contents. So you can handle tuple shapes and values. Try following example of matching tuples -

Example

object Demo {
  def main(args: Array[String]): Unit = {
    val intTuple: (Matchable, Matchable, Matchable) = (1, 2, 3)
    val stringTuple: (Matchable, Matchable) = ("Scala", "Java")
    val mixedTuple: (Matchable, Matchable, Matchable) = (1, "Scala", 3.14)

    println(matchTuple(intTuple))
    println(matchTuple(stringTuple))
    println(matchTuple(mixedTuple))
  }

  def matchTuple(tuple: Any): String = tuple match {
    case (1, 2, 3) => "Tuple of Int: (1, 2, 3)"
    case ("Scala", "Java") => "Tuple of Strings: (Scala, Java)"
    case (_, "Scala", _) => "Tuple with Scala in the middle"
    case _ => "Unknown tuple"
  }
}

Save the above program in Demo.scala. Use the following commands to compile and execute this program.

Command

> scalac Demo.scala
> scala Demo

Output

Tuple of Int: (1, 2, 3)
Tuple of Strings: (Scala, Java)
Tuple with Scala in the middle

Matching Tuples with Fixed Size

You can match tuples of a specific size to ensure they conform to expected lengths. This is used for validating tuple structures. The syntax is -

Syntax

tuple match {
  // logic for tuple with exactly 2 elements
  case (a, b) =>
  // logic for tuple with exactly 3 elements
  case (a, b, c) =>
  // default case
  case _ =>
}

Try following example for matching tuples with fixed sizes -

Example

object Demo {
  def main(args: Array[String]): Unit = {
    val pair: (Matchable, Matchable) = (1, 2)
    val triplet: (Matchable, Matchable, Matchable) = (1, 2, 3)

    println(matchFixedSizeTuple(pair))
    println(matchFixedSizeTuple(triplet))
  }

  def matchFixedSizeTuple(tuple: (Matchable, Matchable)): String = tuple match {
    case (a, b) => "Tuple with exactly 2 elements"
    case _ => "Tuple with unknown size"
  }

  def matchFixedSizeTuple(tuple: (Matchable, Matchable, Matchable)): String = tuple match {
    case (a, b, c) => "Tuple with exactly 3 elements"
    case _ => "Tuple with unknown size"
  }
}

Save the above program in Demo.scala. Use the following commands to compile and execute this program.

Command

> scalac Demo.scala
> scala Demo

Output

Tuple with exactly 2 elements
Tuple with exactly 3 elements

Pattern Matching with Tuple Elements

You can pattern match specific elements within tuples to extract and process values. The syntax is as follows -

Syntax

tuple match {
  // logic for tuples with three elements
  case (first, second, third) => 
  // default case
  case _ => 
}

Try following example for matching pattern with elements of tuple -

Example

object Demo {
  def main(args: Array[String]): Unit = {
    val numbers: (Matchable, Matchable, Matchable) = (10, 20, 30)

    println(matchTupleElements(numbers))
  }

  def matchTupleElements(tuple: (Matchable, Matchable, Matchable)): String = tuple match {
    case (first, second, third) => s"First: $first, Second: $second, Third: $third"
    case _ => "Tuple does not have exactly 3 elements"
  }
}

Save the above program in Demo.scala. Use the following commands to compile and execute this program.

Command

> scalac Demo.scala
> scala Demo

Output

First: 10, Second: 20, Third: 30

Matching Tuples of Different Types

You can handle tuples containing different types by pattern matching on the type of each element. The syntax is as follows -

Syntax

tuple match {
  // logic for tuples with specified types
  case (a: Int, b: String, c: Double) => 
  // default case
  case _ => 
}

Try following example for matching tuples of different types -

Example

object Demo {
   def main(args: Array[String]): Unit = {
      val mixedTuple: (Matchable, Matchable, Matchable) = (1, "Scala", 3.14)

      println(matchDifferentTypesTuple(mixedTuple))
   }

   def matchDifferentTypesTuple(tuple: (Matchable, Matchable, Matchable)): String = tuple match {
      case (i: Int, s: String, d: Double) => s"Int: $i, String: $s, Double: $d"
      case _ => "Tuple does not match expected types"
   }
}

Save the above program in Demo.scala. Use the following commands to compile and execute this program.

Command

> scalac Demo.scala
> scala Demo

Output

Int: 1, String: Scala, Double: 3.14

Handling Nested Tuples

You can match nested tuples to handle more complex data structures. You can tuple inside tuples. The syntax is as follows -

Syntax

tuple match {
  // logic for nested tuples
  case ((a, b), (c, d)) => 
  // default case
  case _ => 
}

Try following example for handling nested tuple -

Example

object Demo {
  def main(args: Array[String]): Unit = {
    val nestedTuple: ((Matchable, Matchable), (Matchable, Matchable)) = ((1, 2), (3, 4))

    println(matchNestedTuple(nestedTuple))
  }

  def matchNestedTuple(tuple: ((Matchable, Matchable), (Matchable, Matchable))): String = tuple match {
    case ((1, 2), (3, 4)) => "Nested tuple: ((1, 2), (3, 4))"
    case _ => "Unknown nested tuple"
  }
}

Save the above program in Demo.scala. Use the following commands to compile and execute this program.

Command

> scalac Demo.scala
> scala Demo

Output

Nested tuple: ((1, 2), (3, 4))

Guards in Tuple Patterns

You can use guards in pattern matching to add additional conditions. The syntax is as follows -

Syntax

tuple match {
  // logic with guard condition
  case (a, b, c) if condition => 
  // default case
  case _ => 
}

Try following example for guards in tuple pattern -

Example

object Demo {
  def main(args: Array[String]): Unit = {
    val numbers: (Matchable, Matchable, Matchable) = (10, 20, 30)

    println(matchWithGuards(numbers))
  }

  def matchWithGuards(tuple: (Matchable, Matchable, Matchable)): String = tuple match {
    case (first: Int, second, third) if first > 5 => s"First is greater than 5: $first"
    case _ => "Tuple does not match guard condition"
  }
}

Save the above program in Demo.scala. Use the following commands to compile and execute this program.

Command

> scalac Demo.scala
> scala Demo

Output

First is greater than 5: 10

Combining Tuple Patterns with Other Patterns

Tuple patterns can be combined with other patterns to handle more complex matching. The syntax is as follows -

Syntax

(tuple, otherPattern) match {
  // logic for combined patterns
  case ((a, b), otherPattern) => 
  // default case
  case _ => 
}

Try following example for combining tuple with other patterns -

Example

object Demo {
  def main(args: Array[String]): Unit = {
    val mixedTuple: (Matchable, Matchable) = (Person("Alice", 25), Dog("Rex"))

    println(matchCombinedPatterns(mixedTuple))
  }

  case class Person(name: String, age: Int) extends Matchable
  case class Dog(name: String) extends Matchable

  def matchCombinedPatterns(tuple: (Matchable, Matchable)): String = tuple match {
    case (Person(name, age), Dog(dogName)) => s"Person: $name, Dog: $dogName"
    case _ => "Unknown pattern"
  }
}

Save the above program in Demo.scala. Use the following commands to compile and execute this program.

Command

> scalac Demo.scala
> scala Demo

Output

Person: Alice, Dog: Rex

Advanced Tuple Patterns

You can use advanced patterns to match complex and variable-length tuples. The syntax is as follows -

Syntax

tuple match {
  // logic for tuple starting with a specific element
  case (first, _*) => 
  // logic for tuple with specific second element
  case (_, second, _*) => 
  // default case
  case _ => 
}

Try following example for advanced tuple patterns -

Example

object Demo {
  def main(args: Array[String]): Unit = {
    val advancedTuple: (Matchable, Matchable, Matchable, Matchable, Matchable) = (1, 2, 3, 4, 5)

    println(matchAdvancedPatterns(advancedTuple))
  }

  def matchAdvancedPatterns(tuple: (Matchable, Matchable, Matchable, Matchable, Matchable)): String = tuple match {
    case (1, _, _, _, _) => "Tuple starts with 1"
    case (_, 2, _, _, _) => "Tuple has 2 as the second element"
    case _ => "Unknown pattern"
  }
}

Save the above program in Demo.scala. Use the following commands to compile and execute this program.

Command

> scalac Demo.scala
> scala Demo

Output

Tuple starts with 1

Tuples Pattern Matching Summary

  • You can match Tuples by structure and contents.
  • You can match tuples of specific sizes to conform to expected lengths.
  • You can also match specific elements within tuples to extract and process values.
  • Tuples containing different types can be handled by pattern matching on the type of each element.
  • You can match nested tuples and tuples with guards in pattern matching to add more conditions.
  • You can combine tuple patterns with other patterns to handle more complex matching.
  • You can also use advanced patterns to match complex and variable-length tuples.
Advertisements