# How to pattern match an array with unknown length

I’ve been digging into pattern matching more in Haxe. I don’t see anything in the docs or cookbook about matching on arrays with unknown length. Here’s a code example of what I’m trying to achieve:

``````function getSpecialTail(array: Array<Int>): Array<Int> {
return switch(array) {
case [4, 8, 12, tail ...]:
tail;
case _:
[];
}
}
``````

`trace(getSpecialTail([4, 8, 12, 5, 8, 7]));`
`>>` [5, 8, 7]

I’m using the ellipsis to signify some operator to let the compiler know to match on any number of elements left in the array. Is there a way to do that?

Thanks.

According to the manual, there’s no way to do this (“arrays can be matched on fixed length”).

I imagine if Haxe ever gets an OCaml target, you would be able to use that `::` operator in pattern matching and also on arrays (`case [4, 8, 12] :: tail:`).

you can use this workaround. Not really efficient thou

``````function getSpecialTail(array: Array<Int>): Array<Int> {

function slice(array:Array<Int>, length:Int):Array<Int> {
return array.slice(0, length);
}

return switch(array) {
case slice(array, 3) => [4, 8, 12]:
return array.slice(3);
case _:
[];
}
}
``````

try it

I’m not generally opposed to supporting this, but there are some aspects that have to be considered. Without a length check, switching on an empty `Int` array on static targets would match `[0, ...]` and `[0, 0, ...]` etc. if we simply access each element of the pattern in the array. This means that we’d need a `>=` check for each pattern, and that in turn leads to grouping and ordering considerations.

Maybe this would make a good haxe-evolution proposal.

FWIW it’s implemented here: Tinkerbell Language Extensions
As for allowing the `...rest` notation (instead of `@rest rest`), it would require prefix `...` to become a syntactically valid unary prefix operator, as suggested here: Allow `...` as a unary prefix operator. · Issue #7234 · HaxeFoundation/haxe · GitHub

1 Like

How is this transformed? Does it support multiple `@:rest rest` in the same pattern? That would seem to increase complexity significantly.

Nope, multiple @rest is not supported. It might actually have multiple solutions, so that’s a bit of a problem.

As for the transformation, it’s pretty dumb actually:

``````case [a1, a2, ..., aX, @rest rest, b1, b2, ..., bY]:
//becomes
case {
before: _.slice(0, X),
after: _.slice(_.length - Y),
between: _.slice(X, _.length - Y)
} => {
before: [a1, a2, ..., aX],
after: [b1, b2, ..., bY],
between: rest
}
``````

So yeah, there’s the unnecessary allocation for prefix and postfix. OTOH it doesn’t have the 0-padding problem for static platforms you mentioned.

1 Like