6.4.9 Extractors

since Haxe 3.1.0

Extractors allow applying transformations to values being matched. This is often useful when a small operation is required on a matched value before matching can continue:

 enum Test {  TString(s:String);  TInt(i:Int); } class Main {  static public function main() {  var e = TString("fOo");  switch (e) {  case TString(temp):  switch (temp.toLowerCase()) {  case "foo": true;  case _: false;  }  case _:  false;  }  } } 

Here we have to capture the argument value of the TString enum constructor in a variable temp and use a nested switch on temp.toLowerCase(). Obviously, we want matching to succeed if TString holds a value of "foo" regardless of its casing. This can be simplified with extractors:

 enum Test {  TString(s:String);  TInt(i:Int); } class Main {  static public function main() {  var e = TString("fOo");  var success = switch(e) {  case TString(_.toLowerCase() => "foo"):  true;  case _:  false;  }  } } 

Extractors are identified by the extractorExpression => match expression. The compiler generates code which is similar to the previous example, but the original syntax was greatly simplified. Extractors consist of two parts, which are separated by the => operator:

  1. The left side can be any expression, where all occurrences of underscore _ are replaced with the currently matched value.
  2. The right side is a pattern which is matched against the result of the evaluation of the left side.

Since the right side is a pattern, it can contain another extractor. The following example "chains" two extractors:

 class Main {  static public function main() {  switch (3) {  case add(_, 1) => mul(_, 3) => a:  trace(a);  }  }  static function add(i1:Int, i2:Int) {  return i1 + i2;  }  static function mul(i1:Int, i2:Int) {  return i1 * i2;  } } 

This traces 12 as a result of the calls to add(3, 1), where 3 is the matched value, and mul(4, 3) where 4 is the result of the add call. It is worth noting that the a on the right side of the second => operator is a capture variable.

It is currently not possible to use extractors within or-patterns:

 class Main {  static public function main() {  switch ("foo") {  // Extractors in or patterns are not allowed  case(_.toLowerCase() => "foo") | "bar":  }  } } 

However, it is possible to have or-patterns on the right side of an extractor, so the previous example would compile without the parentheses.