Sequences (anything built from the IS Scala library classes) can be pattern-matched using the class name (constructor) (e.g., ISZ) as illustrated in the example below.

   
   // Patterns in declarations - sequences

   val seq1 = ISZ("a", "b", "c")
   var ISZ(str1,_,str3) = seq1
   assert(str1 == "a" && str3 == "c")

   // match case - basic sequence matching

   @pure def matchSeq(seq: ISZ[Z]): Option[Z] = {
      seq match { // pattern match on sequence seq
         case ISZ(n1, n2, n3) => return Some(n1 + n2 + n3)
         case ISZ(n1, n2) => return Some(n1 + n2)
         case ISZ(n1) => return Some(n1)
         case ISZ() => return Some(0)
         case _ => return None()
      }
   }

   assert(matchSeq(ISZ(4,5,6)) == Some(15))
   assert(matchSeq(ISZ()) == Some(0))
   assert(matchSeq(ISZ(4,5,6,7)) == None[Z]())    // need to give element type for None to make Slang type-checker happy

The following example illustrates nested matching for sequence containing tuples.


   // match case - nested matching on sequences

   @pure def matchSeqNested(seq: ISZ[(String,String)]): B = {
      seq match { // pattern match on sequence of pairs
         case ISZ(("a",_), ("a",_)) => return T      // matching tuples in sequences (nesting patterns)
         case _ => return F
      }
   }

   assert(matchSeqNested(ISZ(("a","HHH"),("a","JJJ"))))
   assert(!matchSeqNested(ISZ(("b","KKK"))))

Patterns for Slang sequences (IS and MS) can use the Scala sequence wildcard _* which matches 0 or more elements of a sequence.


   // match case - sequence wildcards  _*

   @pure def matchSeqWildcard(seq: ISZ[Z]): B = {
      seq match {
         case ISZ(hd, _*) => return T          // sequence wildcard _* matches 0 or more elements of a sequence
         // case ISZ(hd, tl @ _*) => return T  // ERROR: naming _* via pattern binding NOT SUPPORTED IN SLANG
         case _ => return F
      }
   }

   assert(matchSeqWildcard(ISZ(5,4,3,2,1)))  // _* matches 4,3,2,1
   assert(matchSeqWildcard(ISZ(5,4)))        // _* matches 4
   assert(matchSeqWildcard(ISZ(5)))          // _* matches 0 elements
   assert(!matchSeqWildcard(ISZ()))

One might hope to take advantage of the pattern binding concept to name the “tail” of the sequence in the example above. The grammar for Scala pattern sequences indicates that this is accepted in Scala, but it is not supported in Slang.

Scala Connection

Slang pattern matching on sequences is similar to Scala’s (see, for example, this tutorial).

Sequence pattern matching in both Scala and Slang is based on the fact that Scala allows pattern matching using constructors of non-case classes as long as the class defines an unapply or unapplySeq methods (these are called “extractor patterns” see Scala documentation for pattern matching). This is the strategy used to realize pattern matching for the IS family of Slang types, since IS is a Slang library class that is not a case class (similarly for MS).

However, Slang’s pattern matching is limited to matching on the primary constructor (e.g., ISZ(...)) and, in contrast to Scala, does not support matching on infix operations such as +:, ::, or :+. This means that one cannot use Slang pattern matching to break a sequence apart into named head and tail (e.g., hd +: tl) (as one might want to do when using sequences in a manner similar to cons-based lists in a functional language). Retreiving a named Slang sequence head can be accomplished using the sequence wildcard (e.g., ISZ(hd, _*)). To enable pattern matching with the sequence wildcard, Scala classes must implement the unapplySeq method, and Slang IS and MS supports this.

Note

JH: To Robby, check the description above ….