Last active
March 10, 2018 00:29
-
-
Save ralexstokes/990d83e512825d2c87d2355b38e7e16e to your computer and use it in GitHub Desktop.
Non-recursive prefix calculator as an excuse to try out `clojure.spec`
This file contains hidden or 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 spec-calculator.core | |
(:require [clojure.spec.alpha :as s])) | |
(def ops {'+ + | |
'- - | |
'* * | |
'/ /}) | |
(defn op-for [op] | |
(get ops op)) | |
(def input-regex | |
(re-pattern | |
(str "^\\(\\S[\\s+\\d+]*\\)$"))) | |
(s/def ::input | |
(s/and string? | |
#(re-matches input-regex %))) | |
(defn conform-or-throw [spec input msg] | |
(let [c (s/conform spec input)] | |
(if (= c ::s/invalid) | |
(throw (ex-info msg (s/explain-data spec input))) | |
c))) | |
(defn parse-input [input] | |
(read-string (conform-or-throw ::input input "invalid input"))) | |
(s/def ::operator? | |
(s/and symbol? | |
(into #{} (keys ops)))) | |
(s/def ::computation | |
(s/cat :operator ::operator? | |
:args (s/+ number?))) | |
(defn parse-computation [c] | |
(conform-or-throw ::computation c "invalid computation for the calculator")) | |
(defn run [input] | |
(let [{:keys [operator args]} (-> input | |
parse-input | |
parse-computation)] | |
(apply (op-for operator) args))) | |
(comment | |
(run "(+ 1 1)")) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment