Pattern Matching in Fennel

Published Sun Feb 11 2024

While continuing to learn Fennel everything is syntactically different. The lisp style is new to me, so I have been getting tripped up with the basics like if while getting started. This weekend I worked on a fennel module for sorting the alphanumeric ids I use for my Zettelkasten notes. This gave me an opportunity to try out case matching in Fennel! It took me a little while to understand, I am now beginning to understand the power here.

Why Pattern Match?

Pattern matching is one of my favorite language features. Pattern matching is an elegant way to handle many branches of logic, often simplifying or compacting what would otherwise be a series of if/else statements. Fennel takes this a few steps beyond what I am used to in JavaScript and TypeScript by using tables for patterns.

Example

Here is the case expression I ended up with while working on a comparator function for sorting ids. This case sets the value of result, a variable used to sort our ids. On the first line we have a table [a_val b_val]. The first table provided to case is what patterns are then evaluated against. After this value patterns are provided in [table] (expression) pairs.

(case [a_val b_val]
  [x x] (set result nil)
  [x nil] (set result false)
  [nil y] (set result true)
  (where [x y] (> x y)) (set result false)
  (where [x y] (< x y)) (set result true)
))

Patterns

The first 3 lines in this example have tables to match against. You will notice here there are variables x and y. These are just variable names, the documentation uses a and b, but I had used those names in an upper scope already.

[x x]

This first table uses x twice. This will match if both values in the provided table are equal, or in other words if x is in both slots.

[x nil]

This second table has nil in the second slot. This will match if the provided table has any value in the first slot, and nil in the 2nd. For example: [1, nil]

The following case: [nil x] is for the opposite scenario.

(where [x y] (> x y))

Last are the special where cases. where is a utility provided for cases that require additional logic. Here I want to handle cases for greater and less than, and where does just that!


I am still enjoying the challenge of a different syntax. Lisp is very different from what I am used to and pushes me to understand programming more fundamentally. My Fennel code is still very amateur, I’m looking forward to getting better at it!