Please add your own tips and tricks! You can edit this file from Github by clicking then pencil icon in the top right of the file view.
(m/defsyntax ending-with [end]
['_ '... end])
(m/rewrite
[1 2 3 4 5]
(ending-with ?x)
?x)
;;=> 5
(m/rewrite
[:a :b [1 2 3]]
[:a :b (ending-with ?x)]
?x)
;;=> 3
(m/match {:pair [2 [3 [4 5]]]}
(m/with [%pair [!as (m/or %pair !bs)]]
{:pair %pair})
[!as !bs])
;; => [[2 3 4] [5]]
You can use ..!n
as a subsequence grouping facility, and with
to define a recursive pattern.
(m/rewrite [1 2 3 0 4 5 6 0 7 8 0 9]
(m/with [%split (m/or [!xs ..!n 0 & %split]
[!xs ..!n])]
%split)
[[!xs ..!n] ...])
;; => [[1 2 3] [4 5 6] [7 8] [9]]
You can use m/cata
to recursively apply the same pattern for identifying a separator and subsequent values.
Here we group odd numbers after even numbers together.
(m/rewrite [2 3 5 4 3 2]
[] [] ; The base case for no values left
[(m/pred even? ?x) . (m/pred odd? !ys) ... & ?more]
[[?x [!ys ...]] & (m/cata ?more)])
;; => [[2 [3 5]] [4 [3]] [2 []]]
(m/match {1 2 3 4 5 6}
{& (m/seqable [!ks !vs] ...)}
[!ks !vs])
;; => [[1 3 5] [2 4 6]]
Use a library like hickory
to parse the HTML into data structures, then you can match either the DOM or hiccup.
$
is a convenient way to search for matches in sub-trees.
(m/search (fetch-as-hiccup company-directory-page)
(m/$ [:div {:class "directory-tables"}
. _ ...
[:h3 _ ?department & _]])
?department)
Patterns can call themselves with the m/cata
operator.
This is like recursion.
You can leverage self recursion to accumulate a result.
(m/rewrite [() '(1 2 3)] ;; Initial state
;; Intermediate step with recursion
[?current (?head & ?tail)]
(m/cata [(?head & ?current) ?tail])
;; Done
[?current ()]
?current)
;; => (3 2 1)
When you have a match pattern that contains a memory varible !n
and a substitution pattern where you want to make use of the variable in multiple ways, you can't do that directly because [!n !n]
would take 2 different values out of !n
instead of the same value twice. However, you can easily create two names for the same value in the search pattern with (m/and !n !n2)
which will match a single value, but create 2 memory variables.
(me/rewrite [[:a 1] [:b 2] [:c 3]]
[[!k (me/and !n !n2)] ...]
[[!k !n (me/app str !n2)] ...])
;; => [[:a 1 "1"] [:b 2 "2"] [:c 3 "3"]]
You can use meander.strategy.epsilon/top-down
or bottom-up
to find and replace.
(def p
(s/top-down
(s/match
(m/pred string? ?s) (keyword ?s)
?x ?x)))
(p [1 ["a" 2] "b" 3 "c"])
;; => [1 [:a 2] :b 3 :c]
Say you want to match a number that may be followed by a string, and then a keyword:
[1 "this is fine" :foo]
[1 :foo]
Zeta will include a regex style ?
operator.
Prior to zeta there are 3 ways to handle optional values:
a) Write separate patterns:
(m/match [1 "this is fine" :foo]
[(m/pred number? ?n) (m/pred string? ?s) ?k]
"first case!"
[(m/pred number? ?n) (m/pred keyword? ?k)]
"second case!")
;; => "first case!"
b) Use recursion:
(m/match [1 "this is fine" :foo]
[(m/pred number? ?n) & (m/with [%tail [(m/pred keyword? ?k)]]
(m/or [(m/pred string? ?s) & %tail]
(m/and (m/let [?s nil])
%tail)))]
[?n ?s ?k])
;; => [1 "this is fine" :foo]
c) Constrain a memory variable to length <= 1:
(m/match [1 "this is fine" :foo]
(m/and
[(m/pred number? ?n) . (m/pred string? !s) ..?sn (m/pred keyword? ?k)]
(m/guard (<= ?sn 1)))
[?n (first !s) ?k])
;; => [1 "this is fine" :foo]
Can you improve this documentation? These fine people already did:
Timothy Pratley, Joel Holdbrooks & Jimmy MillerEdit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close