Pattern matching

Leap
Leap in Racket
(define (leap-year? year)
  (define divisible-by-4 (zero? (modulo year 4)))
  (define divisible-by-100 (zero? (modulo year 100)))
  (define divisible-by-400 (zero? (modulo year 400))) 
  (match (list divisible-by-4 divisible-by-100 divisible-by-400)
    [(list _ _ #t) #t]
    [(list _ #t _) #f]
    [(list #t _ _) #t]
    [_ #f]))

The match form compares an expression sequentially to a series of clauses that contain patterns describing the contents of that expression and values returned when a given pattern is matched. For this exercise, this takes the form of creating a list containing three Boolean values representing whether a year is divisible by 4, 100, or 400. As an example, let's run through this code assuming year is set to 1993. (divisible-by-4 1999) is #f, (divisible-by-100 1999) is #f, and (divisible-by-400 1999) is #f. Filling in these results below, we have four patterns underneath it:

(match (list #t #f #f) ; assuming the year is 1999
  [(list _ _ #t) #t]
  [(list _ #t _) #f]
  [(list #t _ _) #t]
  [_ #f])

The first three expect a list of three elements (_ matching any value), but they differ on which value in the pattern can only be the literal value #t.

The first clause [(list _ _ #t) #t] describes a series of checks where the year must at least be divisible by 400. A year divisible by 400 is also divisible by 4 and 100 so we can safely assume all three checks returned #t and there's no need to specify the result. If this pattern is matched, #t is returned. 1999 isn't divisible by 400 since the #f in the third position means the pattern isn't matched.

The second clause [(list _ #t _) #f] describes a series of checks where the year must at least be divisible by 100. A year divisible by 100 is also divisible by 4 so we can be sure that other check returned true and there's no need to specify it here. We can also assume a year divisible by 100 wouldn't be divisible by 400 because if it were, the previous pattern would have already matched. If this pattern is matched, #f is returned. 1999 isn't divisible by 100 since #f in the second position means the pattern isn't matched.

The third clause [(list #t _ _) #t] describes a series of checks where the year must at least be divisible by 4. If this pattern is matched, #t is returned. 1999 isn't divisible by 4 since #f in the first position means the pattern isn't matched.

The fourth clause [_ #f] features a pattern with a single _, which means any value at all can match this pattern. Without such a clause, an exception will occur if none of the clauses' patterns matched. 1999 isn't divisible by 4, 100, or 400, but it matches this catch-all pattern after not matching the previous patterns. As a result, #f is returned by the code.

13th Nov 2024 · Found it useful?