Skip to content

Instantly share code, notes, and snippets.

@aleksandersumowski
Last active November 10, 2019 13:01
Show Gist options
  • Save aleksandersumowski/32a11656b22fe29b6b820ca71b61a063 to your computer and use it in GitHub Desktop.
Save aleksandersumowski/32a11656b22fe29b6b820ca71b61a063 to your computer and use it in GitHub Desktop.
pattern matching libraries

The problem was to pattern match on two values with a guard predicate checking condition across both values.

Specifically to check whether account has enough limit to perform a transaction. I wanted to extract current account limit and transaction amount from incoming event, then check whether amount is less then the limit.

Below are implementations in three different pattern matching libraries.

Meander is the nicest. Supports the behaviour I would expect.

core.match couldn't bind the values from the matched maps to pass to the guard predicate. I had to destructure the maps to get the values within the predicate, kinda defeating the purpose of the pattern matching.

Akar seems to have a bug which the author of the library promises to fix. After that I hope to be able to use first class patterns in order not to have to be repeative in the patterns section.

(ns meander.meander
(:require [meander.epsilon :as m]))
(m/match {:state {:limit 100}
:transaction {:amount 130}}
(m/and {:state {:limit ?limit}
:transaction {:amount ?amount}}
(m/guard (< ?amount ?limit))) (- ?limit ?amount)
{:state {:limit ?limit}
:transaction {:amount ?amount}} "error")
(ns meander.meander
(:require [meander.epsilon :as m]))
(defn within-limit [{{limit :limit} :state
{amount :amount} :event}]
(< amount limit))
(cm/match [{:state state
:event event}]
[{:state {:limit limit}
:event {:amount amount}}
:guard within-limit] (- limit amount)
[{:state {:limit limit}
:event {:amount amount}}] "error")
akar.cljakar.clj (ns akar
(:require [akar.syntax :as a]))
;; doesn't work due to a bug in guard
;; alwats matches first pattern
(a/match [state event]
(:guard (:seq [{:limit limit} {:amount amount}]) <) (- limit amount)
(:seq [{:limit limit} {:amount amount}]) "error")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment