customcommander
customcommander

Reputation: 18931

Why does matching clauses order matter when matching a map?

Given x and y, both designed to match a map with the same matching clauses. The only difference is in the order of the clauses:

(ns so.example
  (:require
   [clojure.core.match :refer [match]]))

(defn x [m]
  (match m
    {:a _} :a0
    {:a _ :b _} :ab0))

(defn y [m]
  (match m
    {:a _ :b _} :ab0
    {:a _} :a0))

I want to match {:a 1 :b 2}:

(x {:a 1 :b 2})
;=> :a0
(y {:a 1 :b 2})
;=> :ab0

The function y has produced the expected result for the given map.

Admittedly I may not understand how the algorithm works but I was under the impression that clojure.core.match would somehow work out that {:a _ :b _} is somewhat more specific than {:a _} and would therefore try that first.

Which is why I'm surprised to see that the order of the matching clauses seems to matter.

Why is that or what am I doing wrong?

Upvotes: 1

Views: 133

Answers (1)

akond
akond

Reputation: 16045

The way the match calculates a pattern score can't discern {:a _} from {:a _ :b _}, which it probably should. What you can do instead, is to tell it specifically there is no :b in the map.

(m/match [{:a 1 :b 2}]
         [({:a _} :only [:a])] :a0
         [{:a _ :b _}] :ab0)

Upvotes: 1

Related Questions