[swift-evolution] Pattern matching with Arrays

Jacob Bandes-Storch jtbandes at gmail.com
Sun Jan 15 16:58:36 CST 2017

On Tue, Jan 3, 2017 at 10:10 AM, Joe Groff via swift-evolution <
swift-evolution at swift.org> wrote:

> On Dec 22, 2016, at 7:43 PM, Robert Widmann <devteam.codafi at gmail.com>
> wrote:
> Do you think there’s room for a more general Pattern Synonyms-like
> <https://ghc.haskell.org/trac/ghc/wiki/PatternSynonyms> feature that
> could extend this to things that look tuple-y?  We had a short conversation
> on Twitter 'round about the release of Swift 1.2 about Swiftz’s HList
> <https://github.com/typelift/Swiftz/blob/master/Sources/HList.swift#L185> implementation
> and my desire to be able to destructure them into tuples for native pattern
> matching.
> My personal favorite design for user-extensible pattern syntax is F#'s
> "active pattern" feature, which lets you declare a set of mutual exclusive,
> total or partial conditions along with a function body that computes which
> condition holds. For the specific case of container patterns, though, I
> feel like it's worth keeping a close association with Collection semantics,
> so that:
> - [] matches when the incoming collection's startIndex == endIndex,
> - [<pattern>, <pattern-list>] fails if startIndex == endIndex, or else
> matches collection[startIndex] against <pattern> and recursively matches
> collection[startIndex.advancedBy(1)..<endIndex] against [<pattern-list>]
> - [<pattern>...] matches the remaining collection against <pattern>
> -Joe

This is really cool. I've never used F#, so thanks for pointing this out.
active-patterns  Extra points for the name (| "banana clips" |).

I've had something like this on my backburner-wishlist for a while.
Customizable patterns/bindings could be very powerful.

One use case I had in mind: writing parsers for binary formats such as
msgpack <http://msgpack.org/index.html>. For instance, msgpack encodes a
uint16 as 0xcd + high byte + low byte. If the 0xcd could be given as a
parameter to the "active pattern", you could imagine writing something like

match msgpackStream {  // a raw byte stream

// Scan 3 bytes, the first of which is equal to 0xcd.
// Theoretical syntax allowing a custom stream-scanner object to fill in
the two variable bindings
// by reading bytes from the stream. If the first byte were not 0xcd, the
match would fail.
case [0xcd, let hi, let lo]:
    return UInt16(hi) << 8 | UInt16(lo)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170115/a80cbf90/attachment.html>

More information about the swift-evolution mailing list