Created
April 28, 2011 17:48
-
-
Save pepijndevos/946857 to your computer and use it in GitHub Desktop.
seqex - a tiny pattern matcher in Clojure
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defproject seqex "1.0.0-SNAPSHOT" | |
:description "a tiny pattern matcher" | |
:dependencies [[org.clojure/clojure "1.2.1"]] | |
:source-path "" | |
:aot [seqex] | |
:omit-source true) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns seqex | |
(:import [clojure.lang | |
Fn | |
IPersistentVector | |
IPersistentMap])) | |
(defn cps [funct cont] | |
(fn [[f & r]] | |
(when-let [f (funct f)] | |
(when-let [r (cont r)] | |
(if (true? r) | |
(if (true? f) [] [f]) | |
(if (true? f) r (cons f r))))))) | |
; (and (funct f) (cont r)))) | |
(def _ (constantly true)) | |
(def end nil?) | |
(defmulti matcher type) | |
(defn match [pattern items] | |
((reduce #(cps (matcher %2) %1) | |
(rseq pattern)) | |
items)) | |
(defmethod matcher :default [l] | |
(partial = l)) | |
(defmethod matcher Fn [f] f) | |
(defmethod matcher IPersistentVector [pattern] | |
(partial match pattern)) | |
(defmethod matcher IPersistentMap [pattern] | |
(fn [m] | |
(every? identity | |
(for [[k v] pattern] | |
(when-let [mv (get m k)] | |
((matcher v) mv)))))) | |
(defmethod matcher java.util.regex.Pattern [pattern] | |
(partial re-find pattern)) ; returns match | |
(defn store [pattern] | |
(fn [s] | |
(when ((matcher pattern) s) | |
s))) | |
(defmacro cond-let | |
[& clauses] | |
(when clauses | |
(list `if-let (first clauses) | |
(if (next clauses) | |
(second clauses) | |
(throw (IllegalArgumentException. | |
"cond-let requires an even number of forms"))) | |
(cons `cond-let (next (next clauses)))))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(match | |
[1 | |
[3 _ end] | |
{:a even?, :b #(= 2 (count %))} | |
end] | |
[1 [3 5] {:a 4, :b [1 2], :d :a}]) | |
; [] (is truthy) | |
(match [1 2 3 _] [1 2 3 4 5 6 7 8]) | |
; [] | |
(let [[x y] (match | |
[1 #"\w.+?\w" 3 (store _) end] | |
[1 "foo bar" 3 4])] | |
(dotimes [_ y] (println x))) | |
; foo | |
; foo | |
; foo | |
; foo | |
; nil |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment