Lisp syntax

Over on Exercism, they have something called The #48in24 Challenge. I'm not exactly sure what it's about, but it started this week with the leap year problem.

This is a fun little problem. A leap year in the Gregorian calendar is a year that is divisible by 4, unless it's divisible by 100, in which case it's only a leap year if it's also divisible by 400.

  • 2023 was not a leap year (not divisible by 4).

  • 2024 is a leap year (divisible by 4, but not 100).

  • 1900 was not a leap year (divisible by 100, but not 400).

  • 2000 was a leap year (divisible by 400).

They don't have a Fennel track, but since I've been doing Fennel lately, that's what I tried.

(fn leap-year? [year]
  (and (= (% year 4) 0)
       (or (~= (% year 100) 0)
           (= (% year 400) 0))))

Turns out I had already done it some years ago in Clojure, which is also a Lisp.

(defn leap-year? [year]
  (and (= (mod year 4) 0)
       (or (not= (mod year 100) 0)
           (= (mod year 400) 0))))

They also have an Emacs Lisp track, so I did it there too.

(defun leap-year-p (year)
  (and (= (% year 4) 0)
       (or (not (= (% year 100) 0))
           (= (% year 400) 0))))

Now, there are other ways to do this, but these are all the same algorithm. Lisp is famous for its elegance and lack of syntax, yet I am struck by how many differences there are. Different keywords for function, different ways to write not equals, even different ways to spell modulo. And these examples are tiny. I guess there is more syntax in Lisp than I usually consider. And these are just three Lisps. There's also Common Lisp and Scheme and Racket and…

Update: As was pointed out to me on Mastodon, this isn't really a syntax issue. The only new syntax above is the square brackets in Fennel and Clojure.