Skip to content

Instantly share code, notes, and snippets.

@miner
Last active June 26, 2016 13:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save miner/5224709 to your computer and use it in GitHub Desktop.
Save miner/5224709 to your computer and use it in GitHub Desktop.
An infix data-reader
(ns miner.infix)
;; Inspired by the excellent book "The Joy of Clojure".
;; http://fogus.me/fun/unfix/infix-src.html
;;
;; Converted to be used as a data-reader by Steve Miner. The main change is to preserve
;; the prefix forms rather than calculating the result. Also, the reader gets symbols, not
;; the actual functions.
(def && #(and % %2))
(def || #(or % %2))
(def ops '[- + * / < > && || =])
(def rank (zipmap ops (iterate inc 1)))
(def op? rank)
(defn infix
[[a b & [c d & m]]]
(cond
(vector? a) (recur (list* (infix a) b c d m))
(vector? c) (recur (list* a b (infix c) d m))
(op? b) (if (and d (< (rank b 0) (rank d 0)))
(recur (list a b (infix (list* c d m))))
(recur (list* (list b a c) d m)))
:else a))
(def infix-reader infix)
(comment
(binding [*data-readers* {'x/infix #'infix-reader}]
(read-string "#x/infix [2 + 3 * 4]"))
;=> (+ 2 (* 3 4))
(binding [*data-readers* {'x/infix #'infix-reader}]
(read-string "#x/infix [2 * b + 10 * [7 - a]]"))
;=> (+ (* 2 b) (* 10 (- 7 a)))
;; for any kind of user input it would be better to use clojure.edn
(clojure.edn/read-string {:readers {'x/infix #'infix-reader}} "#x/infix [2 * b + 10 * [7 - a]]")
;=> (+ (* 2 b) (* 10 (- 7 a)))
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment