Ruby 2.7 introduces pattern matching, it is nicely supported by dry-monads 1.3+.
# presumably you do it in a class with `include Dry::Monads[:result]` case value in Success(Integer => x) # x is bound to an integer in Success[:created, user] # user is bound to the second member in Success(Date | Time) # date or time object in Success[1, *] # any array starting with 1 in Success(String => s) if s.size < 100 # only if `s` is short enough in Success(counter: Integer) # matches Success(counter: 50) # doesn't match Success(counter: 50, extra: 50) in Success(user: User, account: Account => user_account) # matches Success(user: User.new(...), account: Account.new(...), else: ...) # user_account is bound to the value of the `:account` key in Success() # corresponds to Success(Unit) in Success(_) # general success in Failure[:user_not_found] # matches Failure([:user_not_found]) or Failure[:user_not_found] in Failure[error_code, *payload] # ... end
In the snippet above, the patterns will be tried sequentially. If
value doesn't match any pattern, an error will be thrown.
case value in Some(Integer => x) if x > 0 # x is a positive integer in Some(Float | String) # ... in None # ... end
case value in List[Integer] # any list of size 1 with an integer in List[1, 2, 3, *] # list with size >= 3 starting with 1, 2, 3 in List # empty list end
dry-monads treats all wrapped array values as tuples rather than lists. For example, this will not work:
Success([1, 2, 3]) in Success(numbers) # => no match!
But this will:
Success([1, 2, 3]) in Success(one, two, three)
And this will too:
Success([1, 2, 3]) in Success[1, 2 ,3]
To capture an array value, use
Success([1, 2, 3]) in Success(*numbers)
At least for
Failure values, people use tuples more often; this is why dry-monads treats all arrays as tuples. We could make
Failure behaviors different, but this would be even more unexpected.