Last active
October 26, 2017 14:03
-
-
Save danielneal/d82c142c9eab9f8caec0fa93b87ff7f3 to your computer and use it in GitHub Desktop.
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 stupidsense.core | |
(:require [clojure.spec.alpha :as s] | |
[clojure.string :as str] | |
[clojure.core.specs.alpha])) | |
(def blacklist-ns #{"clojure.core"}) | |
(defn fn-specs [registry] | |
(into {} (for [[sym spec] registry | |
:let [form (s/form spec)] | |
:when (and (not (contains? blacklist-ns (namespace sym))) | |
(seqable? form) | |
(= (first form) 'clojure.spec.alpha/fspec))] | |
[sym form]))) | |
(s/def | |
::fn-spec | |
(s/cat :fspec- #{'clojure.spec.alpha/fspec} | |
:args- #{:args} | |
:args (s/spec (s/cat :cat- #{'clojure.spec.alpha/cat} | |
:args (s/* (s/cat :arg keyword? :spec any?)))) | |
:ret- #{:ret} | |
:ret any? | |
:fn- #{:fn} | |
:fn any?)) | |
(def arg-spec | |
(s/spec (eval (-> (s/conform ::fn-spec (s/form a-spec)) | |
:args | |
:args | |
first | |
:spec)))) | |
(defn arg-specs | |
[fn-spec] | |
(let [conformed (s/conform ::fn-spec fn-spec) | |
args (get-in conformed [:args :args])] | |
(for [{:keys [arg spec]} args] | |
[arg {:spec-form spec | |
:spec (s/spec (eval spec))}]))) | |
(defn format-option [fn-name substitute-arg arg-specs value] | |
(apply list fn-name (for [[arg {:keys [spec spec-form]}] arg-specs] | |
(if (= arg substitute-arg) | |
value | |
(symbol (str "?" (name arg))))))) | |
(defn applicable [registry value] | |
(let [fn-specs (fn-specs registry)] | |
(for [[fn-name fn-spec] fn-specs | |
:let [arg-specs (arg-specs fn-spec)] | |
arg-spec arg-specs | |
:let [[arg {:keys [spec spec-form]}] arg-spec] | |
:when (s/valid? spec value)] | |
(format-option fn-name arg arg-specs value)))) | |
(s/fdef make-bigger | |
:args (s/cat :x int?) | |
:ret int?) | |
(defn make-bigger [number] | |
(inc number)) | |
(s/def ::first-name string?) | |
(s/fdef make-greeting | |
:args (s/cat :person (s/keys :req-un [::first-name])) | |
:ret string?) | |
(defn make-greeting [person] | |
(str "Hello, " (get person :first-name))) | |
(s/fdef square-root | |
:args (s/cat :num (s/and number? pos?)) | |
:ret map?) | |
(defn square-root [num] | |
(Math/sqrt num)) | |
(s/fdef d | |
:args (s/cat :d (s/and number? #(> % 5))) | |
:ret map?) | |
(s/fdef add | |
:args (s/cat :a number? :b number?) | |
:ret number?) | |
(defn add [a b] | |
(+ a b)) | |
(defn huge-number? [num] | |
(> num 100000)) | |
(s/fdef huge-number? | |
:args (s/cat :num number? ) | |
:ret boolean?) | |
;; WILD DEMO | |
(applicable (s/registry) 3) | |
;; ((stupidsense.core/make-bigger 3) | |
;; (stupidsense.core/square-root 3) | |
;; (stupidsense.core/huge-number? 3) | |
;; (stupidsense.core/add 3 ?b) | |
;; (stupidsense.core/add ?a 3)) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment