Scala, odpowiednik C# aktywnych wzorców F#

Scala, odpowiednik C# aktywnych wzorców F#

Zastrzeżenie:nie znam F#.

W scala, jeśli wartość ma metodę o nazwie unapply (lub unapplySeq), zostanie użyta do dopasowywania wzorców.

Definicja rezygnacji z zastosowania to:

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

Jeśli None to return oznacza brak dopasowania, Some((t1, ..., tn)) oznacza, że ​​dopasowanie zakończyło się sukcesem i może być powiązane z wartościami od t1 do tn

A potem może być używany jako:

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

Jeśli dopasowanie może mieć dynamiczną liczbę wyników, to unapplySeq jest używany, który zwraca Option[List[T]]

Wreszcie, jeśli żadne zmienne nie muszą być powiązane podczas dopasowywania, unapply może po prostu zwrócić wartość logiczną

Przykłady:

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

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

.r Metoda zamienia ciąg w Regex. Ta klasa ma metodę unapplySeq, która dopasowuje grupy w wyrażeniu regularnym.

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

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

W tym przypadku składnia case class tworzy obiekt singleton o tej samej nazwie (osoba) z metodą unapply pasującą do argumentów konstruktora.

AKTUALIZACJA:Oto jak zdefiniować Even i OddFirst, trochę uogólnienia. Zarówno parzyste, jak i nieparzyste można wyrazić za pomocą funkcji, ale musimy dostosować tę funkcję do specyfikacji ekstraktorów, to znaczy zastosować ją przez unapply

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

Teraz możemy użyć tego (pokazując dwa sposoby)

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

I użyj:

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

Możesz osiągnąć tę funkcjonalność za pomocą funkcji scala zwanej Extractors.

Dla twojego parzystego/nieparzystego przykładu:

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")
}

To samo można osiągnąć w Scali. Koncepcja nazywa się Ekstraktory. Składnia ich definiowania jest nieco brzydsza niż wydaje się w F#. Podam pierwszy przykład:

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

Twój drugi przykład też się sprawdza. Musisz zwrócić obiekty DateTime z metody unapply. Podaję tutaj link, gdzie możesz przeczytać więcej na ten temat.