Beyond when: introducing case/in

Free preview 4 min to read

A different question than case/when answers

The previous course, "Ruby logic: standard checks", ended with case/when. It answers one kind of question well: which of these possibilities does this single value match? grade_letter and day_type both checked one value against a list.

This course covers a different tool, case/in, called pattern matching. It answers a different question: does this value have a certain shape, and if so, what pieces does it break into?

A motivating example

Picture an array that holds a coordinate pair. Your code needs to check that it has two elements and pull both out.

point = [3, 4]

case point
in [x, y]
  puts "x is #{x}, y is #{y}"
end
# x is 3, y is 4

in [x, y] does two things at once. It confirms that point is an array of two elements, no more and no fewer, and it binds those elements to new local variables, x and y, inside the pattern itself.

case/when can check whether an array equals [3, 4]. It has no way to say "an array of any two things, and hand me both of them."

Why this is called pattern matching

[x, y] describes a shape with two slots, not two specific values. Ruby compares that shape with the real value. If the shape fits, the slots are filled with whatever was there.

case [3, 4]
in [x, y]
  puts "matches: #{x}, #{y}"
end

case [3, 4, 5]
in [x, y]
  puts "this won't print, three elements don't fit a two-slot pattern"
else
  puts "no match"
end

The second case falls through to else, because [3, 4, 5] has three elements and [x, y] describes two. Pattern matching checks the structure first, and it only fills the slots once the structure fits.

Where you'll meet this shape

Ruby code often returns a small array that says what happened. A common convention is a pair whose first element is a symbol, like [:ok, value] or [:error, message].

result = [:error, "email is taken"]

case result
in [:ok, user]
  puts "created #{user}"
in [:error, message]
  puts "failed: #{message}"
end
# failed: email is taken

:ok and :error are plain values inside the pattern, so they must match as written. user and message are empty slots, so they capture whatever sits in the second position. One case checks which kind of result arrived and pulls out its payload in the same step. The same idea works on hashes, which is how parsed JSON usually arrives, and lesson 3 covers it.

Not a replacement, an addition

This course doesn't retire case/when, because the two do different jobs. case/when is the right tool for checking one flat value against several possibilities, such as grade_letter's ranges. case/in is the right tool when the value is a compound structure, an array or a hash, and you want to check its shape and extract its pieces in one step. Lesson 6 draws that line precisely.

What this course covers

  1. Beyond when: introducing case/in. Pattern matching answers a different question (you are here).
  2. Matching array structure. Arrays by shape, including a splat for "the rest" and a search for one element.
  3. Matching hash structure. Hashes by key, without requiring every key to be present.
  4. Guards and the pin operator. An extra condition a matched shape must also satisfy, and matching against a variable you already have.
  5. Alternatives, ranges and =>. One of several shapes in a single in clause, value patterns, and capturing what matched.
  6. case/in vs case/when, and one-line matching. A decision rule, the one behavioral difference, and the one-line forms.
  7. Putting it together. A small challenge that uses everything.

You only need to read array and hash literals here, such as [3, 4] and {name: "Ada"}. The two courses after this one, "Ruby collections: arrays" and "Ruby collections: hashes", teach them properly.

By the end, you'll recognize when a value's shape matters as much as its content, and you'll reach for case/in when it does.

Lesson 1 of 7 · free

Keep going with lesson 2

Matching array structure

Covers fixed-length array patterns, ignoring positions with _, nested patterns, splats and the find pattern.

A free account also gives you the quizzes, your progress and notes, and the discussion.

Type to start searching...