This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-12-23
Channels
- # ai (1)
- # beginners (84)
- # boot (111)
- # cider (2)
- # cljsrn (9)
- # clojure (245)
- # clojure-italy (2)
- # clojure-mke (1)
- # clojure-russia (6)
- # clojure-spec (92)
- # clojure-uk (32)
- # clojurescript (55)
- # core-async (1)
- # cursive (8)
- # datomic (19)
- # events (1)
- # hoplon (379)
- # lambdaisland (4)
- # lein-figwheel (8)
- # off-topic (115)
- # om (18)
- # om-next (5)
- # onyx (25)
- # re-frame (8)
- # reagent (5)
- # ring-swagger (1)
- # rum (19)
- # schema (3)
- # untangled (24)
@johnmarinellii The next time you do pretty much anything with Leiningen, it will update. You rarely need to run lein deps
these days.
If you start a REPL via lein repl
or “jacking in” from Emacs or another editor, that should trigger the update.
@seancorfield ok that’s what i had thought - however when i launch a cider nrepl instance from emacs i get WARNING: CIDER's version (0.8.1) does not match cider-nrepl's version (0.9.0)
Have you tried lein repl
outside Emacs?
@johnmarinellii based on that error, it may be that you need to update cider in emacs - nrepl is reporting 0.9.0, but cider says 0.8.1
@ballpointcarrot , that….makes sense. ty 🙂
(realizing i should have just read the error message)
I can never remember which way round that error message works!
calling stacktrace.root-cause
with my throwable seems to return a data structure closer to what I want, but I can’t figure out how to pull any values off of the returned object
and just a heads up, CIDER is 0.14 on stable and 0.15 on melpa. and it now handles its nrepl dependency so you can remove that from your profile file if/when you update
@seancorfield I think im bitten by this :
(or "2" 1)
=> "2"
read-string
is a bit of a sledgehammer to crack a nut because it will read any Clojure expression and potentially execute code.
If you're expecting an integer, you're much safer using (or (Long/parseLong x) 1)
that will only convert a string into a long (integer), without the risk of executing any code, or it will throw an exception if it is given anything other than a numeric string.
You might be at a point where clojure.spec
is useful...
(require '[clojure.spec :as s])
(s/conform (s/int-in 1 471) page)
checks 1 <= page < 471We have specs for all our APIs, that accept strings that can be conformed to numbers in particular ranges
(defn ->long [s] (try (Long/parseLong s) (catch Exception _ ::s/invalid)))
(s/def ::page (s/and ->long (s/int-in 1 471)))
That will conform strings to integers in the range 1..470, or else produce something you can check with s/invalid?
(let [page-num (s/conform ::page page)] (if (s/invalid? page-num) (handle-the-error) (use-the-number page-num)))
You always have to handle invalid input somehow.
(you'll need something slightly different to handle nil
in amongst all this)
Hmm, the above isn't quite right but it should point you in the right direction...
@seancorfield does spec work in 1.8 ?
Well, there's a backport library for it... but we're using Clojure 1.9 Alpha 14 in production already...
boot.user=> (require '[clojure.spec :as s])
nil
boot.user=> (defn ->long [s] (try (Long/parseLong s) (catch Exception _ ::s/invalid)))
#'boot.user/->long
boot.user=> (s/def ::page (s/and (s/conformer ->long) (s/int-in 1 471)))
:boot.user/page
boot.user=> (s/def ::optional-page (s/nilable ::page))
:boot.user/optional-page
boot.user=> (let [page nil page-num (or (s/conform ::optional-page page) 1)] page-num)
1
boot.user=> (let [page "42" page-num (or (s/conform ::optional-page page) 1)] page-num)
42
boot.user=> (let [page "a" page-num (or (s/conform ::optional-page page) 1)] page-num)
:clojure.spec/invalid
boot.user=> (let [page "500" page-num (or (s/conform ::optional-page page) 1)] page-num)
:clojure.spec/invalid
Something like that... You can test (if (s/invalid? page-num) (bad-stuff) (good-stuff page-num))
We're using spec pretty heavily in production. 1.9 is basically 1.8 + spec so the core is the same.
@seancorfield oke, one question : Can I also make a spec for a function that take a clojure object and filter some things out of it. Things like name and so on ?
@roelofw yes you can define data structures in Spec.... that's its whole raison d'etre
oke, so I can make a spec to test this function :
(defn read-numbers
"Reads the ids of the paintings"
[response]
(->> (:body response)
:artObjects
(map :objectNumber)))
I think I can do it like this one :
def email-regex #"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,63}$")
(s/def ::email-type (s/and string? #(re-matches email-regex %)))
(s/def ::acctid int?)
(s/def ::first-name string?)
(s/def ::last-name string?)
(s/def ::email ::email-type)
(s/def ::person (s/keys :req [::first-name ::last-name ::email]
:opt [::phone]))
one thing what is not clear to me. Do I have to place the specs in the test directory or only the (s/test .... ) and the rest in the same file as the code I want to test
I’m in a similar situation where i need to do this. I know this is a hack but is there any alternative way of doing it? http://stackoverflow.com/questions/27652176/clojure-is-it-possible-to-execute-multiple-expressions-in-a-cond-case
(cond
(> a 0) (when true
(println a)
(println (* a a))
:else (str "do nothing")
))
`@roelof For your purposes, it’s probably easier to put the specs in the source files, but in general “it depends” — at World Singles, we tend to have specs in separate namespaces (but still in the source tree) since we are mostly specifying data structures, rather than functions.
You also have the option of running different kinds of tests. If you spec your functions, you can have your test code call s/instrument
to add spec-based instrumentation while you are running your tests: that will verify that functions are called with correct arguments (but that doesn’t check results, nor the “invariants” of the functions). You can also use clojure.spec.test/check
to have Clojure generate (conforming) test data for you and exercise your function with lots of example data.
In addition, you can use spec directly in your source code to validate arguments and conform input data to your specified model.
clojure.spec
brings a lot of power and a lot of features so there’s a lot to learn about using it — but it’s definitely worth the effort.
@seancorfield oke, so I can use spec to test my read-data function I post earlier
So I have then to use s/instrument
and 'clojure.spec.test/check` if I understand you right
@roelof It is not even a year old / in the public. This guide: http://clojure.org/guides/spec is pretty good 🙂
so I found there a example how I could make tests for the read-data functions and the others that I use
@sveri it looks to me that spec could be a the testing/validation platform for clojure
I could try to implement the code sean gave me in read-data . Also there the page schould be between 1 and 471.
@roelof https://m.youtube.com/watch?v=VNTQ-M_uSo8 this is a good Talk about spec where stuart compares it to other type systems among other things.
i heard people were talking about spec in here so figured i'd drop by... trying to finish up speccing a project before i refactor it and am having trouble with just a few things
mainly, i want to construct a list of s/def
s to pass as the arguments and return values of a s/fdef
and then probably run s/exercise
on it, but am not getting the syntax right
@sophiago I am not sure if I understand you exactly, but, this is how I use spec: https://github.com/sveri/getless-clj/blob/master/src/clj/de/sveri/getless/db/food.clj
@kevinbheda I would definitely either use a do
form as suggested, or put the multiple other things you want to do into their own function