Fork me on GitHub
#beginners
<
2019-07-05
>
seancorfield02:07:22

@deleted-user I would do something like (is (s/valid? ::some-spec a-valid) (s/explain ::some-spec a-valid)) -- untested but should be close.

seancorfield02:07:06

assert throws an exception which isn't very useful in a test.

dharrigan09:07:34

To clarify, I see that creating a def inside a defn is considered bad practice, is this because that def will create a new global binding, i.e., that bound var could be accessed anywhere in the namespace? The proper approach (I know this, I'm just clarifying my thoughts) is to use let which creates a new lexically scoped var, that once the let is done, the var is unbound?

Alex Miller (Clojure team)11:07:49

let doesn’t create a var at all, just a local binding

dharrigan12:07:42

thank you Alex for clarifying, I guess I was trying to find the right word, but now I have it! πŸ™‚

Alex Miller (Clojure team)13:07:42

local bindings are also much lighter weight in terms of the compiler and compiled code as well (all local, not global)

dharrigan14:07:15

thank you πŸ™‚

noisesmith09:07:24

@dharrigan not only is it accessible anywhere, but if your function is run concurrently, both instances are mutating the same shared value, a classic source of errors

dharrigan09:07:53

ooh, that is dangerous

dharrigan09:07:36

thanks. I was asked by a colleague why not do as I explaining some clojure to him, I think I did okay, but didn't mention about the concurrency issue!

noisesmith09:07:30

one of the best things about clojure is that if we write normal code, it's automatically thread safe, but that means our definition of "normal code" can't include def inside defn :D

jaihindhreddy13:07:45

I've been using agents to perform http requests, and I'm wondering how to respect 429s and rate limit myself. Is that possible with vanilla agents, or do I need something else? I can tolerate some (< 15 %) requests not going.

noisesmith13:07:05

since agent actions are serialized, you could have the agent send itself #(Thread/sleep n) followed by re-sending the same function it was executing

noisesmith13:07:51

any new actions would get queued up to run after the sleep and the retry are done

seancorfield15:07:32

@johnjelinek Glad you found it useful!

johnjelinek15:07:21

Indeed! I've been using vscode instead of atom, but there's a lot I want to copy from your video.

seancorfield17:07:13

@johnjelinek Feel free to reach out with any questions you might have about the workflow etc.

πŸ‘ 4
Andrea Imparato17:07:06

πŸ‘‹ anybody here use compojure-api? I'm trying to run https://github.com/metosin/compojure-api-examples

Andrea Imparato17:07:12

^ this is what I get

hiredman17:07:28

the example repo is really old, and likely using an old broken version of unify

seancorfield17:07:58

Yeah, this came up a few days back -- let me search Zulip for the info...

hiredman17:07:50

if you run it with the versions as specified in the repo I would expect it to work

Andrea Imparato17:07:39

how is compojure-api for building rest api?

Andrea Imparato08:07:52

thank you very much very much appreciated (as usual :))

Andrea Imparato17:07:48

i mean, is it good or bad?

seancorfield17:07:20

Looks like the old version of the lein-ring plugin is probably the issue here -- based on the discussion mirrored to Zulip from February, but I thought it came up more recently...

dpsutton17:07:22

this came up for me twice this week and was related to an outdated lein-ring plugin. i think you want 0.5.12 maybe?

dpsutton17:07:04

0.12.5 it seems

seancorfield17:07:53

compojure-api is fine for building REST APIs. We use plain Compojure, and JSON middleware at work for our REST APIs.

seancorfield17:07:15

(so I should probably say "our REST-like APIs" πŸ™‚ )

Andrea Imparato17:07:06

eheh πŸ‘ yeah I want to use it for a pet project just to practice a bit with web development πŸ™‚

clj 4
πŸ•ΈοΈ 4
dharrigan19:07:30

I've had nice success with clj-http-rest

dharrigan19:07:45

oh, that's for client, not as a server

Alex Miller (Clojure team)19:07:49

either is the same result

Alex Miller (Clojure team)19:07:16

I'd say, don't be afraid of using words in test names :) like test->maze-constructor-function is perfectly good too

Alex Miller (Clojure team)19:07:36

6 months later when it fails and prints that in your console, it may be helpful :)

dpsutton21:07:11

what's your issue? how is laziness vs strictness hurting you?

seancorfield21:07:16

@deleted-user Do you mean that you only want the expression in the "message" position to be evaluated if the test fails?

seancorfield21:07:18

(is (= "Success!\n" (s/explain-str :grid/maze (g/->maze 2 3))))
πŸ™‚

seancorfield21:07:08

user=> (t/is (= "Success!\n" (s/explain-str even? 42)))
true
user=> (t/is (= "Success!\n" (s/explain-str even? 43)))

FAIL in () (NO_SOURCE_FILE:1)
expected: (= "Success!\n" (s/explain-str even? 43))
  actual: (not (= "Success!\n" "43 - failed: even?\n"))
false
user=> 

seancorfield21:07:25

(reify Object (toString [_] (s/explain-str even? 43))) -- but the resulting message is wrapped in #object[ ... ]

seancorfield21:07:21

Actually, is is a macro so I suspect it doesn't evaluate the msg form unless the test fails... let me verify that...

seancorfield21:07:01

Ah, that's a shame πŸ™‚

dmaiocchi21:07:15

Moin, I'm trying to import a java lib from maven with leinigen. The library is this one: https://github.com/prometheus/client_java

dmaiocchi21:07:50

[io.prometheus/simpleclient "version"] should be ok right?

dmaiocchi21:07:17

[io.prometheus/simpleclient "0.6.0"] ok so worked.. First time I import a java lib 😁 I did a typo before that's why didn't worked.. 😁

seancorfield22:07:26

@deleted-user Something to consider if you want to test with specs is to use expectations/clojure-test which provides more expressive tests. For example:

(! 537)-> clj -Sdeps '{:deps {expectations/clojure-test {:mvn/version "RELEASE"}}}'
Clojure 1.10.1
user=> (require '[expectations.clojure.test :refer [expect]])
nil
user=> (require '[clojure.spec.alpha :as s])
nil
user=> (s/def ::foo even?)
:user/foo
user=> (expect ::foo 42)
true
user=> (expect ::foo 43)

FAIL in () (NO_SOURCE_FILE:1)
43 - failed: even? spec: :user/foo

expected: (=? :user/foo 43)
  actual: (not (=? :user/foo 43))
false
user=> 

clj 4
seancorfield22:07:51

You can use expect in place of is inside deftest.

seancorfield22:07:09

I started using Expectations years ago, after seeing it presented at Clojure/West. Eventually (as with so many libraries!) I ended up taking over as maintainer. But it always bothered me that the core Expectations library is not compatible with clojure.test. That's what I wrote expectations/clojure-test

seancorfield22:07:09

It's basically the syntax from the original Expectations library (that first link), transplanted into the clojure.test environment.

seancorfield22:07:06

We use it for almost everything at work. Works with Cognitect's test-runner, for example. Works with Cursive as well I believe (which does some fancy stuff with test failures).

seancorfield22:07:50

It runs a clojure.test-compatible suite.

seancorfield22:07:05

There are lots of test runners out there.

seancorfield22:07:50

clojure.test needs a test runner in order for you to run tests from the command-line.

seancorfield22:07:10

lein test is another test runner (again, expecting something clojure.test-compatible).

seancorfield22:07:36

(CIDER is also a test runner, among other things)

seancorfield22:07:39

There's an #expectations channel if you get deeper into that library and have questions. I'll notice them more easily there.

πŸ‘ 4