I saw this deck via Haskell Weekly Recap which noted an interesting property:
“x is a leap year if and only if
gcd(80, x) > gcd(50, x)
”
(gcd = ‘greatest common divisor’) which I haven’t fully appreciated the origin of, but wanted to try some implementations. The deck shows a Haskell version
leapyear = liftA2 (>) (gcd 80) (gcd 50)
filter leapyear [1890..1920]
[1892,1896,1904,1908,1912,1916,1920]
and it took me a few minutes to fully grasp, but once I did, I’m very happy with it. I recently worked through this fantastic post explaining Functors, Applicatives, and Monads using a mix of Haskell and Typescript and it actually sunk in.
What other languages could I try? Of course, I had to try R
leapyear <- function(year) {
pracma::gcd(80, year) > pracma::gcd(50, year)
}
Filter(leapyear, 1890:1920)
#> [1] 1892 1896 1904 1908 1912 1916 1920
No point-free coding here, we need an actual argument to the function. It’s also disappointing that R doesn’t have a built-in greatest common divisor, so calling out to a package for that one. Otherwise, I’m not disappointed by this.
This brought me to wanting to try it in (Dylog) APL which does have a built-in GCD (∨
) and does tacit/point-free quite nicely
leapyear ← (80∨⊣) > 50∨⊢
years ← 1890+⍳30
(leapyear years)⌿years
1892 1896 1904 1908 1912 1916 1920
It took me a few attempts to get the tacit bits working but this is also quite nice, I feel.
Fun stuff!!!
Edit: After a really interesting meetup with some J programmers, I realised I can use bind (∘
) to make this properly tacit in APL
leapyear←(80∘∨)>(50∘∨)