Fork me on GitHub
Michael Lan02:04:37

Cant quite find what the recommended solution to this is on the interwebs:


To not use :refer :all. Instead, use an alias:

[cheshire.core :as :ch]


(ch/parse-string ...)
Or manually refer to the functions you use:
[cheshire.core :refer [parse-string]]

Michael Lan02:04:53

Oh, so that message is basically telling me doing :refer :all is a bad practice 😅


This is to avoid polluting your namespace by referring to all kind of functions that you never use. It’s the same reason why :use is not recommended, and to easily know where a function comes from

👍 6

@U01ML6ZL2U8 as a good rule of thumb "always use :as with an alias", and it's common to use the last unique segment in the namespace as the alias -- but sometimes a shorter, obvious mnemonic is more readable (:require [cheshire.core :as json]) is something you'll see a lot. In the same way that the most common alias for clojure.string is str.


There are a few things that are okay to :refer in, because it makes the code more readable than using an alias. For example, with clojure.test, it's fine to :refer [deftest is testing] -- and if you look at clojure.core.async code, you'll see folks will typically alias it as async but also :refer in the operators (`<!`, >!, <!!, >!!).


(In tests, I tend to alias the namespace being tested as sut -- system under test -- but that's not very common in the Clojure world I don't think)


I use sut too 🙂


I wonder if it’s more popular in the UK than the USA?


Perhaps we can ask to put it on the next State of Clojure survey 😉


Hey! clojure spec docs say that cat matches a map… > Conforms to map with named keys based on the `cat` tags

(s/explain (s/cat :x int? :y int?) {:x 2 :y 1})
{:x 2, :y 1} - failed: (or (nil? %) (sequential? %))


Why doesn’t this work?


The issue that brought me to this was in trying to match a nested vector.

(s/explain (s/cat :a string? :nested (s/cat :b string? :b string?)) ["a" ["b" "c"]])
gives me
["b" "c"] - failed: string? in: [1] at: [:nested :b]


I guess they’re two distinct questions.

Alex Miller (Clojure team)15:04:27

It conforms (outputs) a map

Alex Miller (Clojure team)15:04:51

cat always matches a sequential coll

Alex Miller (Clojure team)15:04:54

regex ops combine to match a single sequential coll. If you want to match nested colls, wrap the inner one in s/spec


Ah right! Sorry. There’s enough new stuff that I’m already forgetting things. Thanks!


(require '[clojure.spec.alpha :as s])

(require '[clojure.spec.test.alpha :as stest])

(defn fun [i]
  (inc i))

(s/fdef fun
  :args int?)

(stest/instrument `fun)

(fun 8)
(8) - failed: int?
Sorry to be back again so soon. I’m pasting this code into a 1.10.2 clojure repl and I’m getting an error so I don’t think it’s anything with my environment or my other code. I don’t expect an error here, what gives? Thanks in advance!


check out (doc s/fdef). The error is how you are specifying the :args spec


think about how you would have to spec fun if it had two args, and how that would structurally change the :args spec


i'll post the "solution" in a thread but it's worth thinking for a second


(s/fdef fun
  :args (s/cat :i int?))


consider if fun took two arguments. there would be no way to add the second argument's spec to :args without changing the cardinality from 1 to many. The answer is that the args is always a sequence of specs, and in this case it has only one spec


also, notice the error message doesn't say 8 failed: int? but (8) failed: int?.


Oh! I was wondering why it was in parens. I only get it now that I’m thinking about it being in a list.


That was really bothering me, thank you so much for pointing that out.


I’ll need to use s/cat then. Aww man, I totally missed that. Thanks for pointing that out. Yea, it’ll help me to remember to do that if I consider how it would scale to more arguments like you said.

👍 3

I am trying to find a blog post on core.async anti-pattern, any recommendations?