Fork me on GitHub

I want to turn a map like this… {:foo ["a" "b"], :bar ["x" "y"]} … into a vector like this… [{:foo "a", :bar "x"} {:foo "b", :bar "y"}] The size of the vectors in the map’s values is the same for all elements. Any ideas for how to solve this idiomatically?


@msolli :

(let [data {:foo ["a" "b"], :bar ["x" "y"]}
      ks (keys data)]
  (->> (vals data)
       (apply map vector) ;; Transpose the matrix of values
       (mapv (partial zipmap ks))))


The above will not work, however, if keys and vals may return elements in different order


Hm, thanks, seems like they do for a regular hash-map. Docstring for both keys and vals state that they return things “… in the same order as (seq map)“.


Yeah, missed that part.


ordering is the same


yeah, the docstring changed a while back


What's the history of the naming of vec and vector? Are there any regrets?


It appears Clojure zip went for a make- prefix.

Alex Miller (Clojure team)12:06:29

Well I wasn’t there but all data structures use their name as the constructor function - vector, hash-map, hash-set, list, array-map, etc

Alex Miller (Clojure team)12:06:00

I think of vec and set as coercers

Alex Miller (Clojure team)12:06:36

We typically use literal syntax instead of constructors whereas the coercing is more common so it’s convenient to have those be shorter

Alex Miller (Clojure team)12:06:57

But that’s all just me post-rationalizing


In Clojure zip that convention wasn't followed, if I am interpreting correctly. We were trying to name some functions for coercing and creating Java periods. A shortened version is hard to contrive.

Alex Miller (Clojure team)17:06:23

zip-map is map as in map (the operation), not as in hash-map (the collection) - that is, it’s seen as a sequence function more than as a constructor (but I totally get why people say that too)


It appears Clojure zip went for a make- prefix.

Alex Miller (Clojure team)12:06:30

zip almost certainly is echoing that use in other functional langs


I need to read and write TOML files. I see that there are already several Clojure libraries for this. Is there any reason to prefer one of them over the others, or are they all pretty much interchangeable?


I've never used that but quickly looking at options only the last one seems to support writing: * * * That's also the one most recently updated.


I’m having an odd issue with stest/instrument and :stub in the context of deftest.


On the line where I call stest/instrument in a test I get this error: Caused by: java.lang.ClassCastException: clojure.lang.AFunction$1 cannot be cast to clojure.lang.MultiFn


Yet executing that very line in the REPL correctly instruments the function in question, along with the stubbing behavior.


The stacktrace is deep within spec -> test.check, and I cannot figure out the reason for the difference in behavior.


Maybe instrument is meant for use in test.check but not clojure.test ?

Alex Miller (Clojure team)15:06:11

If you’re running in lein, you may be running into lein’s monkey patching of clojure.test

Alex Miller (Clojure team)15:06:24

if so, you can try :monkeypatch-clojure-test false in project.clj (and most likely lose nothing you care about)


That’s good to know!


Hm here's a weird problem. If I turn on reflection warnings, and I evaluate ring-core file src/ring/middleware/session/cookie.clj I get two reflection warnings:

Reflection warning, crypto/random.clj:28:12 - call to static method encodeHex on org.apache.commons.codec.binary.Hex can't be resolved (argument types: unknown).
Reflection warning, crypto/random.clj:28:3 - call to java.lang.String ctor can't be resolved.
But then if I check out crypto-random project and evaluate that random.clj file, I get no reflection warnings.


Figured it out. cryto-random uses ancient commons-codec 1.6, and ring-core uses newer commons-codec 1.11, which has more overloads of encodeHex, which causes the old code to produce reflection warnings.


Seems like lib authors should annotate java interop with types even when not needed, because it can cause grief later.


@weavejester submitted PR in crypto-random.


does anyone have a recommendation for a cloud service for a toy clojure app?


(must have a free plan as well)


I tried google app engine a few years ago and it was a pain


I second heroku. Very easy deploy.


Hey all, I am looking for advice on spec generation: I have a data structure like this

{:item_count 53  :items [ {} {} ...53 times]}
My goals is to write a spec to help generate this data structure, but I need to have item_count to be the total number of items in provided by the :items this possible?

Alex Miller (Clojure team)17:06:46

Totally, you can s/and any arbitrary predicate

Alex Miller (Clojure team)17:06:51

(s/def ::item_count int?)
(s/def ::item map?) ;; whatever
(s/def ::items (s/coll-of ::item))
(s/def ::item-map
  (s/and (s/keys :req-un [::item_count ::items])
	       #(= (:item_count %) (count (:items %)))))
(s/valid? ::item-map {:item_count 2 :items [{} {}]}) ;; => true

Alex Miller (Clojure team)17:06:24

sorry, I didn’t read all of that above

Alex Miller (Clojure team)17:06:35

can also gen, using fmap

Alex Miller (Clojure team)17:06:05

(s/def ::item-map
		  (s/keys :req-un [::item_count ::items])
	    #(= (:item_count %) (count (:items %))))
	    (fn [items] (hash-map :item_count (count items) :items items))
	  	(s/gen ::items))))

Alex Miller (Clojure team)17:06:34

that is gen the items list, then use fmap to produce the right shaped map


Heroku is great, @roti


+1 heroku is pretty easy to get going and the free tier can take you pretty far


somewhere there was a discussion about where to put specs, and one of the suggestions was to stick them in their own namespace, so that the specs for program.widget would be in program.widget.specs. I’m trying to figure out how namespaced keywords would work in practice, but it seems to me that you need the specs to be in the same namespace or they won’t match up. Or am I missing something? Or maybe the idea is to put them in the same namespace but a different file?


the keyword used needs to match between definition and usage


the namespaces can be anything you find meaningful


@nickmbailey Not that it really matters but one of the reasons I appreciate Heroku is that they went out of their way to accommodate deploying Clojure fairly early on in its history


I think it was because they're users of Clojure and have always had Clojure advocates on the inside


but Datomic Ions might be the new "easiest sensible way to deploy a Clojure app"


@noisesmith What I mean is this kind of thing:

~$ clj
Clojure 1.9.0
user=> (in-ns 'spectest.spec)
#object[clojure.lang.Namespace 0x33308786 "spectest.spec"]
spectest.spec=> (clojure.core/require '[clojure.spec.alpha :as s])
spectest.spec=> (s/def ::first-name clojure.core/string?)
spectest.spec=> (s/def ::person (s/keys :opt [::first-name]))
spectest.spec=> (in-ns 'spectest)
#object[clojure.lang.Namespace 0x5911e990 "spectest"]
spectest=> (clojure.core/require '[clojure.spec.alpha :as s])
spectest=> (s/conform :spectest.spec/person {::first-name 42})
#:spectest{:first-name 42}
The spec didn’t really work because the first-name key is defined in one ns but used in another. This isn’t a problem with :req-un because it only matched up the name of the keyword


that's just using aliases wrong


don't use '::'

Alex Miller (Clojure team)20:06:44

:: means “autoresolve in the context of the current namespace”

Alex Miller (Clojure team)20:06:57

you’re using it in two different namespaces and expecting the same result


if you explicitly state the namespace, then you won't have any problems when it resolves to something you don't expect


right, so I would need to construct the map using the spectest.spec namespace


or just namespace the keyword


(sorry it’s confusing that i called it spectest. should be widget vs. widget.spec or something)


which, like I said, the keyword you use to define the spec and the one you use to check it need to match




right got it. the reason i was confused is because I could have sworn that someone was suggesting that by putting the specs in their own namespace, you could decide whether to load them or not. but that’s not really going to be possible if you want to use namespaced keywords


keyword namespaces are not the same thing as code namespaces


namespaced keywords do not belong to namespaces


the only thing that links them is ::, which, see my earlier suggestion not to use it


yea okay. thanks that makes sense


:foo/bar can exist just fine without the namespace foo needing to exist


I think the answer is that as a matter of taste I would want the keywords to be :foo/bar rather than :foo.spec/bar. so I should probably just change the spec and not use :: there as you suggested (?)


that would be my suggestion

👍 4

Hey, I’m trying the following:

(POST "/:partner-id/antifraud-rules" []
       :path-params [partner-id :- ::antifraud/partner_id]
       :body-params [action :- ::antifraud/action
                     criteria :- ::antifraud/criteria]
       :summary "Creates a new rule for given partner."
        ;  (println body)
         (created "" {:rule (antifraud/add-rule-to-partner partner-id action {})})
         (catch PSQLException e
           (unprocessable-entity {:errors ["Invalid fields."]}))))
And my specs are:
(s/def ::action #{"allow" "deny"})
(s/def ::criteria (s/keys :opt-un [::email ::phonenumber ::document]))
And my error is:
  "spec": "(spec-tools.core/spec {:spec (clojure.spec.alpha/keys :req-un [:$spec44286/action :$spec44286/criteria]), :type :map, :keys #{:criteria :action}, :keys/req #{:criteria :action}})",
  "problems": [
      "path": [],
      "pred": "map?",
      "val": null,
      "via": [],
      "in": []
  "type": "compojure.api.exception/request-validation",
  "coercion": "spec",
  "value": null,
  "in": [
What I’m doing wrong? 😞


looks like there should be a map containing :criteria and :action and instead you got nil?


The point is: I’m sending a JSON body with the criteria and action as keys


what are you doing to allow the handler to use json?


I’m using the example from luminus:

(def antifraud-rules-routes
   {:swagger {:ui "/docs/external-antifraud-rules"
              :spec "/antifraud-rules.json"
              :data {:info {:version "1.0.0"
                            :title "Antifraud Rules Service"
                            :description "Create, update and remove rules from antifraud service."}}}}

   (context "/v1/partners" []
     :tags ["Configuration of antifraud."]
     :coercion :spec

     (POST "/:partner-id/antifraud-rules" []
       :path-params [partner-id :- ::antifraud/partner_id]
       :body-params [action :- ::antifraud/action
                     criteria :- ::antifraud/criteria]
       :summary "Creates a new rule for given partner."
        ;  (println body)
         (created "" {:rule (antifraud/add-rule-to-partner partner-id action {})})
         (catch PSQLException e
           (unprocessable-entity {:errors ["Invalid fields."]})))))))


usually the way you get json input is via a ring middleware, wrap-json-body iirc


if that middleware isn't being applied, that would be a simple reason that it wouldn't get any of your input


Oh I see now the problem


I’m missing the json middleware it seems


it probably isn't being added by default because you might not want it applied to everything indescriminately? anyway, it's easy to double check by applying it