« Back to posts

Using core.match with function arguments

17 Feb 2013

Recently I started learning Clojure (partly in preparation for its upcoming section in my tour through seven languages) and I ran into a problem when trying to pattern match on arguments. You can’t just pass them straight to match and expect to follow most current online examples. The types aren’t quite right! You’ll always get back the :else clause or some other odd behaviour.

Function arguments in Clojure are of type ArraySeq (and for good reason), but using core.match with Seqs requires a different (slightly more verbose) syntax. The simplest way to make things work as you might expect is to convert the arguments into a Vector first.

Solution

Use vec to convert the function arguments into a vector before passing them to match:

(use '[clojure.core.match :only (match)])

(defn -main [& args]
    (println (match (vec args)
        ["echo" word] word
        :else "Invalid command")))

Alternate Solution

If spending time and processing power just to spare some syntax is unappealing to you, then I’d recommend using core.match’s Seq Matching capabilities directly:

(use '[clojure.core.match :only (match)])

(defn -main [& args]
    (println (match [args]
        [(["echo" word] :seq)] word
        :else "Invalid command")))

Note the differences:

  1. (match [args] - The arguments are wrapped in a vector instead of being converted to one
  2. [(["echo" word] :seq)] word - Any pattern x is enclosed like so: [(x :seq)]

Hope this has helped!


blog comments powered by Disqus
Content by Nick Knowlson: Google+