-
Notifications
You must be signed in to change notification settings - Fork 449
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pattern matching DSL #3442
Pattern matching DSL #3442
Conversation
Kover Report
|
Cool stuff! Never actually used Optics for pattern matching, knew it was theoretically possible. Can we also supports sealed classes through |
We do! It's there in the example :P |
Oh yes, of course! It's relying on |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SHIP IT!!
public fun <S, R> S.match(cases: MatchScope<S, R>.() -> Unit): R { | ||
val subject = this | ||
val scope = object : MatchScope<S, R> { | ||
override fun <A> Optional<S, A>.then(next: (A) -> R) { | ||
this.getOrNull(subject)?.let { throw MatchFound(next(it)) } | ||
} | ||
override fun default(next: () -> R) { | ||
throw MatchFound(next()) | ||
} | ||
} | ||
try { | ||
cases(scope) | ||
throw IllegalArgumentException("no match found") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we force a default
lambda, and provide a second function matchOrThrow
without the default
lambda?
This way it's less likely to forget to catch IllegalArgumentException
, and if you have no default you are forced to be more explicit.
Haven't taken a full look at the PR yet, but this should definitely have an integration with SingletonRaise so that it fails similarly to Monad.fail from Haskell |
I've just pushed a new commit which I think covers both of your comments:
I like the possibility of having a catch-all case within the DSL, since it mirrors how one usually defines pattern matching. value.match {
User.company.address(Address.street) then { s -> ... }
default { "Unknown address " }
} |
Yes, that looks great, but I felt that the strategy should be explicit in the function names. Thank you, great improvement! |
Late to the party but wanted to say this looks great 👏 |
This PR proposes a small DSL to describe pattern matching. This is based on three ideas:
Optional
s in a row,Optional<S, A> + Optional<S, B> = Optional<S, Pair<A, B>>
invoke
to simulate them.This is an example from the code. Note that
then
separates an optional that matches and the code that uses the information being matched as result.