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:
- The left side can be any expression, where all occurrences of underscore
_
are replaced with the currently matched value. - 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.