Ruby – Pattern Matching – Second Impressions
by Paweł Świątkowski
19 Apr 2019
Since I published A quest for pattern-matching in Ruby 3 years ago, I’ve been called “pattern matching guy” more than once. So obviously, when I learned that PM is inevitably coming to the Ruby core, I was curious to check it out. First Impressions have already been published, so this is “Second Impressions”, from my point of view.
Heads up: it’s very subjective.
I’m mostly judging it by examples provided in the original Redmine ticket, such as:
First of all, the code is ugly in a way that makes it hard to reason about. It looks like being added on top of a language which was not designed to support pattern matching (which is exactly the case). This might not be important in the long run, when people get used to it - but here it is, in the second impressions round.
Destructuring (why was it called deconstruction?) looks nice, but I would remove the pipe thingy. Instead of
e: Integer | Float => i (which is terribly ambiguous - is it
e: (Integer | Float) => i or
((e: Integer) | (Float)) => i, or something else?) it would be better to have a possibility to define a type union like in Pony. For example:
Besides that it’s good, especially for getting things out of hashes.
But probably my most important problem with this proposal is that it does not let me have multiple functions defined with different type signatures, ruled by pattern matching. This is what I’m mostly missing on a daily basis working with Ruby, while having it available in Erlang or Elixir. To give you a taste of what I’m talking about:
Of course, to achieve what’s in code listing above, it would be much larger and complicated change. Basically it would be like introducing proper types to Ruby. It needs to allow having one method defined mutiple times in one class, but without shadowing previous definitions. I don’t think that Ruby will ever go this way, yet this is something that would clean up my code in few places significantly.
I also realised that while working on Noaidi – my implementation of pattern matching. I don’t really want plain pattern matching somewhere in the code, as I can make most cases work with good old
case in Ruby. But I would like to be able to write modules that behave kind of like the ones in Elixir.
And this is being made possible in Noaidi. I have an experimental branch enabling this and I hope I will be able to finish it some day. Such module would look like this:
Verdinct: I’m kind of disappointed. The quest is not over yet.