The syntax of pattern matching #1195
Replies: 3 comments 10 replies
-
I'm just noticing in two of your Hylo examples: for let y: T in x { print(y) } and if (a: 1, b: let y) = x { print(y) } The inconsistency of the placement of OK, you say the 2nd example is “introducing names at arbitrary depths in structural pattern.” The introduced name is if (a: 1, b: _) = x { let y = ??; print(y) } Actually I don't know what I'd even write for Anyway, I'm surely not interpreting your words correctly because not being able to pattern match and bind to a part in one expression seems awfully and needlessly inconvenient. |
Beta Was this translation helpful? Give feedback.
-
See also: https://docs.scala-lang.org/scala3/reference/changed-features/pattern-matching.html |
Beta Was this translation helpful? Give feedback.
-
I find the second syntax a bit confusing. Usually, we are allowed to write the type of the binding after its declaration like @kyouko-taiga earlier mentioned a special where syntax for for loops, I think that would be a better alternative:
...Or some generic algorithm that can utilize pattern matching as predicates. For this, I think the
|
Beta Was this translation helpful? Give feedback.
-
Our implementation of pattern matching has significantly drifted from our specification so I think it may be good to have a look at the current state of things. Today, pattern matching looks like Swift but with a couple of notable syntactic differences.
First, don't use the
is
,as
andas?
operators; instead we use:
to match over types. For example:The reason for having
match
instead ofswitch
is kind of cosmetic but my sense is that Swift picked the latter to make simple switch statements (e.g., over integers) look familiar to a C-family audience. IMO, this construction is going much farther than C's switch and relates more to pattern matching as popularized by other languages like Scala or Ocaml.I find the use of
as
andas?
confusing in Swift. The latter must be used inif
statements and the former in all other forms of matching. This rule seems questionably (pun intended) motivated to me. In contrast, I find:
more concise and using it consistently feels less confusing.A second difference is that we don't use
case
to introduce patterns inif
statement/expression or afor
loop:The absence of
case
makes our statements/expressions more concise without removing clarity. The same couldn't be said inmatch
, however, because patterns may become difficult to identify in that expression if you (as a human) quickly parse it. To understand what I mean, let's examine the following expression:The structure of our AST currently makes it impossible to introduce names at arbitrary depths in structural pattern. For example, this program is syntactically illegal:
I am not sure it is something we actually want, though, so when I discovered the limitation I left it there. We can often rewrite this kind of code using a side condition on the match, or even write another match in the success clause. However, these workarounds are more verbose and so it is quite possible that we may want to lift the limitation.
A last notable change is that optional binding in Hylo must use an optional pattern rather than Swift's more concise syntax. This difference makes optionals behave more consistently w.r.t. to other union types because
let y = x
is irrefutable and doesn't narrowx
's type in Hylo.Note: a variant of the Hylo syntax does exist in Swift.
Ideas for extensions
It would be nice if we could pattern match on non-structural types. Swift has some support of custom patterns but I find it lacking. AFAIK, there's no way to "bind" values with a custom pattern; we can only match existing values.
Custom patterns
One way to support more powerful custom patterns would be to define a trait that requires a projection:
Of course, we could have different effect requirements on
scrutinee
to supportinout
patterns andsink
patterns too.List patterns
I wrote this extension in the utilities of
hc
, which I use all the time.You'll notice that this method relates to a non-empty list pattern in Haskell. It would be nice if we could use it in pattern matching.
I think we could with the following trait:
Beta Was this translation helpful? Give feedback.
All reactions