Fork me on GitHub
#clojure-spec
<
2017-12-04
>
andrea.crotti14:12:10

is this actually valid Clojure?

(defn run-query [service query]
  (let [{::keys [result error]} (invoke-service service {::query query})]
    (or result error)))

andrea.crotti14:12:29

just noticed in the clojure spec documentation https://clojure.org/guides/spec

andrea.crotti14:12:38

should it not be :clojure?

bronsa14:12:47

that's valid clojure yes, why does that confuse you?

danielneal14:12:08

maybe it's those namespaced keywrods

andrea.crotti14:12:32

well it doesn't compile

1. Caused by java.lang.RuntimeException
   Unable to resolve symbol: result in this context

andrea.crotti14:12:44

with ::keys, but it does with :keys

bronsa14:12:46

which version of clojure?

bronsa14:12:01

::keys is 1.9 syntax

denik15:12:27

Is there a way to get a function spec as data?

taylor15:12:56

(s/form `my-fn-name)

bbrinck15:12:02

If you’re looking for the :fn part of an fdef spec, you can use this:

(s/form (:fn (s/spec `my-fn-name)))

stathissideris15:12:26

And you can also dig deeper and get the :args part:

(s/form (:args (:fn (s/spec `my-fn-name))))

denik15:12:20

neat! I forgot to call s/form on the retrieved spec:

(s/form (s/get-spec `foo))

denik17:12:45

can the spec from s/keys be adapted as s/keys* to avoid repetition?

(s/def :foo/id number?)
(s/def ::foo
  (s/keys :req [:foo/id]))              ;; <-----------

(defn new-foo [& {:as attr-vals}]
  ;; add custom attrs
  attr-vals)

(s/fdef new-foo
        :args (s/cat :attr-vals (s/keys* :req [:foo/id])) ;; <----------
        :ret ::foo)

(new-foo :foo/id 1 :foo/bar "baz")

denik17:12:39

(defmacro spec-keys->spec-keys*
  [spec]
  (let [form (s/form spec)]
    (if-let [[_ & args] (and (seqable? form) (= (first form) `s/keys) form)]
      `(s/keys* ~@args)
      (throw (ex-info (str "Not a " `s/keys " form")
                      {:spec spec
                       :form form})))))