Before moving ahead, think for a moment about how would you parse this:
$ cd /
$ ls
dir a
14848514 b.txt
8504156 c.dat
dir d
$ cd a
$ ls
dir e
29116 f
2557 g
62596 h.lst
$ cd e
$ ls
584 i
$ cd ..
$ cd ..
$ cd d
$ ls
4060174 j
8033020 d.log
5626152 d.ext
7214296 k
Certainly, not difficult. Some conditionals and string manipulation here and there, it is the first thing that comes to mind. Though trivial, it may not be obvious or pleasant to read afterward, or for a new pair of eyes.
Ruby 2.7 introduced pattern-matching as an experimental feature, and since Ruby 3.0 it is not considered experimental anymore.
In case you don’t know what pattern matching is, it’s a feature that allows you to specify patterns to match against data. It is similar to regular expression matching, but with the ability to match against arbitrary data structures, rather than just strings.
The content above can be simply pattern-matched this way:
input.split("\n").each do |line|
cmd = line.split(" ")
case cmd
in ["$", "ls"]
# matches listing entries
in ["$", "cd", ".."]
# matches leaving a directory
in ["$", "cd", dir]
# matches entering a directory
in ["dir", dir]
# matches directory entry
in [size, filename]
# matches file entry
end
end
That’s exactly what I did on day 7 of the advent of code! The resolution just came naturally and easily realizing that it would be a perfect case to use pattern-matching.
At first, it seems like a switch-case statement on steroids, which is true, but it’s so much more!
Arrays, hashes, and objects can be matched and bound:
# Matching against arrays
[1, 2, x, 4] = [1, 2, 3, 4] # x is now bound to 3
[a, b, *rest] = [1, 2, 3, 4] # a is bound to 1, b is bound to 2, and rest is bound to [3, 4]
# Matching against hashes
{a: 1, b: 2} = {a: 1, b: 2} # a is bound to 1, b is bound to 2
{a: 1, **rest} = {a: 1, b: 2, c: 3} # a is bound to 1, and rest is bound to {b: 2, c: 3}
# Matching against objects
Point = Struct.new(:x, :y)
point = Point.new(1, 2)
Point.new(x, y) = point # x is bound to 1, y is bound to 2
Give it a try! You won’t regret it!
If you liked this post, consider subscribing to my newsletter Bit Maybe Wise.
You can also follow me on Twitter and Mastodon.
Photo by Georg Eiermann on Unsplash