Scala, C# equivalent of F# active patterns

Disclaimer: I don't know F#.

In scala, if a value has a method named unapply (or unapplySeq), then it will be used in pattern matching.

The definition of unapply is:

object Example {
    def unapply(t: T): Option[(T1, ..., Tn)] = ...
}

If None is return it means no match, Some((t1, ..., tn)) means a match is successful and can be bound to values t1 to tn

And then it can be used as:

value match {
  case Example(t1, ..., tn) => ...
}

If the matching can have dynamic number of results, then unapplySeq is used which returns Option[List[T]]

Finally, if no variables need to be bound when matching, unapply can just return a Boolean

Examples:

val Date = ""(\d{1,2})/(\d{1,2})/(\d{1,2})$".r

"12/12/12" match {
   case Date(m, d, y) => ...
}

The .r method turns a string into a Regex. That class has an unapplySeq method which matches the groups in the regex.

case class Person(name: String, age: Int)

somePerson match {
    case Person(name, age) => ...
}

In this case, the syntax case class creates an singleton object with the same name (Person) with an unapply method matching the constructor arguments.

UPDATE: Here's how to define Even and Odd First, some generalization. Both Even and Odd can be expressed via a function, but we need to make this function conform to the extractors spec, that is, apply it via unapply

class BooleanExtractor[T](f: T => Boolean) { 
  def unapply(t: T) = f(t)
}

Now, we can use like this (showing two ways)

val Even = new BooleanExtractor[Int](_ % 2 == 0)
object Odd extends BooleanExtractor[Int](_ % 2 == 1)

And use:

scala> 3 match {
     |   case Even() => println("even")
     |   case Odd() => println("odd")
     | }
odd

You can achieve this functionality by way of a scala feature called Extractors.

For your even/odd example:

object Even {
  def unapply(x:Int) = if (x % 2 == 0) Some(x) else None
}

object Odd {
  def unapply(x:Int) = if (x % 2 == 1) Some(x) else None
}

3 match {
  case Even(x) => println("even")
  case Odd(x) => println("odd")
}

You can achieve the same in Scala. The concept is called Extractors. The syntax to define them is a bit uglier than in F# it seems. I'll provide the first example:

scala> object Even {def unapply(z: Int) = (z%2 == 0)}                      
defined module Even    
scala> object Odd {def unapply(z: Int) = (z%2 != 0)}                       
defined module Odd    
scala> 2 match {
     | case Even() => "even";
     | case Odd() => "odd";
     | }
res10: java.lang.String = even

Your second example works, too. You have to return the DateTime objects from the unapply method. I provide a link here where you can read more on the topic.

Tags:

C#

F#

Scala