Fork me on GitHub
#clojure
<
2018-06-05
>
lwhorton00:06:29

does clojure.test have a convenient way to do a global fixture? as in creating an account once per test suite, then cleaning up afterword? the (use-fixtures) is on a namespace level, not global, so can I use the namespace dependencies (or something similar) to ensure a catch-all file that’s loaded first?

rutledgepaulv02:06:48

If you’re using leiningen you can do global test setup code in a :injections vector within the project.clj and a jvm shutdown hook for cleanup

rutledgepaulv02:06:55

I’m sure there are other ways but that’s been one that has worked nicely for me.. I use that to start up the server exposed by my application and shut it down after the tests have run. It’s only needed when running on CI agents since if I’m working on the tests myself I’ll just do the setup in my repl

rutledgepaulv02:06:31

something like…

chrisblom09:06:36

what do people use for linting clojure code? So far I’ve tried kibit, eastwood and joker, but all of these tools have lots of false postives.

pesterhazy09:06:23

joker works very well for me

pesterhazy09:06:38

integrated into emacs it's a huge productivity boost

👍 8
pesterhazy09:06:52

what kind of false positives are you seeing?

chrisblom10:06:51

with joker mostly that it cannot resolve symbols

pesterhazy10:06:23

strange, I'm not seeing those (with cljs)

jumar10:06:34

for me joker works reasonably well. The biggest "unresolved symbol" issues are probably with clojure.test (because of :refer :all and clojure spec (`fdef` spec above the function)

pesterhazy11:06:30

You can also, I think, ignore some errors or, failing that, just grep through the output and remove warnings that you want to exclude. Hacky but it works

Candid04:06:15

@U9CQNBXDX make sure you configure :known-macros in .joker file: https://github.com/candid82/joker#reducing-false-positives

jgh10:06:49

does GraalVM work with clojure?

👍 4
souenzzo11:06:05

There is a #graalvm channel. Even datomic works well (not sure about prod setup) https://gist.github.com/souenzzo/c4719d45e804767c97f6f5be1bcdd1c5

tbaldridge11:06:21

In short, asking if "GrallVM works with Clojure" is most likely not the question you think you're asking 😄

jgh14:06:48

heh ok, i will give this a read...i appreciate the link 🙂

gklijs10:06:38

@jgh some things work, it has some limitations

mkvlr12:06:16

I’m conjing onto a list and calling peek on it. This seems to work for a while in my app until it doesn’t and I get java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to clojure.lang.IPersistentStack. It is possible that conj returns a different kind of list depending on the size or should I look elsewhere for a bug?

bronsa12:06:04

conj does return different concrete implementations depending on size (e.g. array-map to hash-map), but not different collection types

bronsa12:06:40

but more importantly conj never returns a LazySeq

bronsa12:06:06

so you’re likely maping over the list before calling peek on it

bronsa12:06:19

peek works on stacks, vectors and lists are stacks but seqs aren’t

bronsa12:06:43

and it looks like you’re using a seq as a stack somewhere

mkvlr12:06:47

@bronsa alright, thanks a lot for the clarification 🙏

gmercer12:06:41

I am using the clojure command line tool, it locks up, strace shows chasing the POMs, on a cyclic dependency (hickey-rage-face) in [org.apache.xmlgraphics/batik-transcoder "1.7"] similar to https://github.com/technomancy/leiningen/issues/1127 - does anyone know a workaround ? @alexmiller

gmercer12:06:18

I was burnt by this in gradle, 7 years ago, to the point of submitting a pull-request https://github.com/gradle/gradle/pull/13/commits/cebaae69dd21049a11240b320c00e79e9ae20a2b I think that time the library was apache fop ...

vemv15:06:26

...I guess the cljs test runner is asynchronous and the JVM one not, or something to that effect

mccraigmccraig19:06:02

@U45T93RA6 on clj there isn't generally a problem with testing async things - you generally get a promise or chan result which you can deref or <!! respectively, neither of which you can do on cljs

Sid16:06:28

I am trying to bring up a service using compojure-api and the swagger-ui seems to have auto-sorted.... is there some way to control the sorting of the JSON responses?

dpsutton16:06:25

can you explain what you are trying to accomplish @sidiv14.it. It sounds like you are trying to sort a hashmap which is asking more from a data structure than it is willing to give

Sid16:06:10

I am trying to see if we can sort the fields in the JSON..

dpsutton16:06:57

json objects are unordered. so there's no guaranteeing that your sorting would be honored

jgh16:06:23

you could wrap whatever objects you want sorted in an array, the order would be honored then.

jgh16:06:32

but you obviously would have to iterate through it to access the objects.

pesterhazy16:06:53

I suppose you could see if there's a JSON serializer that sorts keys, but why would you want/need that?

dpsutton16:06:28

but there's no guarantee that a client would treat the serialized order as important

Sid16:06:09

thanks for the responses guys... wanted to see if thats a possibility.

jgh16:06:09

it's probably better to just have the client sort it however the client wants to sort it

Sid16:06:14

yep I agree... sorting doesn't serve any real purpose in parsing

lilactown17:06:31

I am writing a simple parser/compiler for a hiccup-like DSL. atm I’m using a protocol that dispatches on the type of the first element in the vector, e.g. if it’s a keyword, symbol.

lilactown17:06:50

I’d like to allow a consumer to extend the parser in a way that isn’t just based on type, though. such as for a special :keyword, transform it in some way

lilactown17:06:20

protocols don’t really seem to work well for this. but also, multimethods kind of fall short for this too it feels like.

lilactown17:06:23

is there a common pattern to allow consumers of a library to extend functionality this way?

noisesmith17:06:59

what if your multimethod first tried to match on the value, and if nothing found, then attempted to dispatch on the type?

noisesmith17:06:21

(defmulti dsl-type-based type) (defmulti dsl-value-based identity) (defmethod dsl-value-based :default [x] (dsl-value-based x))

lilactown17:06:21

:thinking_face: that could work!

lilactown17:06:47

I was thinking of allowing a consumer to pass in a custom predicate. But maybe I don't need to be that flexible

tbaldridge17:06:37

@lilactown expand on your reason for not using multi-methods though, they're extremely flexible

4
💯 8
lilactown19:06:37

You can't directly extend the dispatch fn of a multimethod

jsa-aerial23:06:49

(defn d1 [x] (->> x (take 2) vec))
(defn d2 [x] (-> x first :type))
(defn dispatcher [x] (let [f (first x)] (if (fn? f) (f (rest x)) f)))
(defmulti mfoo dispatcher)
(defmethod mfoo :bar [x] "is keyword dispatch")
(defmethod mfoo [:foo :bar] [x] "double keyword")
(defmethod mfoo :my-type [x] "special type")

jsa-aerial23:06:02

Would something like this work for you? @lilactown Basically you extend the dispatcher by 'passing in' custom dispatchers. Or (haven't thought this out), maybe have the dispatcher itself be a multimethod

metacritical18:06:00

@lilactown If one were to use ‘spec’ how would you do without multi-methods?

metacritical18:06:57

I suggest you take a look at spec, it fits perfectly for your use case and you can write a hiccup like parser using spec in 10-15 minutes.

Bravi19:06:17

hi everyone. where am I going wrong? 😄

(defn- resolve-video-provider
  [url]
  (condp (partial s/includes? url)
      "youtube" "YouTube"
      "vimeo" "Vimeo"))

seancorfield19:06:53

@bravilogy condp takes a binary predicate and an expression, followed by a sequence of alternating value / result clauses.

Bravi19:06:45

yeah, I followed the docs and to my understanding, that was supposed to work but I guess I don’t quite get it then

Bravi19:06:58

I thought I would refactor this

(defn- resolve-video-provider
  [url]
  (cond
    (s/includes? url "youtube") "YouTube"
    (s/includes? url "vimeo")   "Vimeo"))

Bravi19:06:04

and make it more DRY

seancorfield19:06:40

It's difficult with s/includes? because condp tests (pred test-expr expr) where expr is the initial expression and test-expr is each of the values in the clauses that follow.

mg19:06:13

you’d need to do something like,

(condp #(s/includes? %2 %1) url "youtube" "YouTube" ...)

seancorfield19:06:25

you'd need

(condp (fn [t e] (s/includes? e t)) url
  "youtube" "YouTube"
  "vimeo" "Vimeo")

Bravi19:06:49

ah I see! ok now I understand

Bravi19:06:54

thank you so much

seancorfield19:06:38

The docstring/reference docs are not really very clear (IMO), but clojuredocs has good examples: http://clojuredocs.org/clojure.core/condp

mg19:06:51

I too am sad that this situation doesn’t let you use partial 😉

dpsutton19:06:23

(fn [{:keys [:keywords]}] keywords) destructure with keywords is allowed. (fn [{:prefix/keys [:keywords]}] keywords) destructure with namespaced keys keyword not allowed. intentional? bug?

Bravi19:06:40

@mg yeah, that’d be very clojury 😄

seancorfield19:06:45

We have a utility function at work, called flip (taken from Haskell), so we could say

(condp (flip s/includes?) url
  "youtube" "YouTube"
  "vimeo" "Vimeo")

mg19:06:00

yeah that would be great

seancorfield19:06:21

(defn flip
  "Like partial except you supply everything but the first argument.
  Also like Haskell's flip for single arity call."
  ([f] (fn [b a] (f a b)))
  ([f b] (fn [a] (f a b)))
  ([f b c] (fn [a] (f a b c)))
  ([f b c d & more]
   (fn [a] (apply f a b c d more))))

mg19:06:42

@dpsutton it’s (fn [{:keys [prefix/sym]} m] ...)

mg19:06:57

the binding will be to sym

seancorfield19:06:41

@mg you can use qualified-`keys`:

user=> ( (fn [{:a/keys [b c]}] (println b c)) {:a/b 1 :a/c 2} )
1 2
nil

dpsutton19:06:41

a new version is {:prefix/keys [without-prefix]}. however, when using a keyword there (as opposed to just a symbol) it barfs with :prefix/keys but not on :keys

mg19:06:53

oh, haven’t seen that form yet

dpsutton19:06:02

yeah its a 1.9 goodie i believe

Bravi19:06:12

@seancorfield I use flip all the time in js from ramda.js library 😄 that’s a neat implementation, thank you

seancorfield19:06:37

@dpsutton I would say it's intentional because :a/k and :k are different -- and I think it's weird that :k is allowed inside [ .. ] in the unqualified case.

dpsutton19:06:55

understood. i can see a rationale either way. just was a bit surprising but makes sense

mg19:06:08

@seancorfield the 1-arity is kind of subtly different from the others and doesn’t quite match the docstring… I guess it’s semantically meaningless for fewer than 2 args

seancorfield19:06:16

@michael.gaare Well, we don't have currying in Clojure -- and if the 1-arity was curried, it would be harder to use.

seancorfield19:06:55

You couldn't use it in condp for a start...

seancorfield19:06:44

(but your point is well-taken)

mg19:06:09

it would be interesting to see it more fully support partial, I think

mg19:06:18

hm, but how would that work

mg19:06:15

yeah, doesn’t make sense

seancorfield19:06:17

@michael.gaare Yeah, it's a bit of an odd compromise due to the fundamental difference between Haskell and Clojure in terms of currying. Haskell doesn't need partial at all, and Haskell's flip can be fully defined in one arity.

mg19:06:17

I never quite understood why condp was written that way, actually. It seems like it’s forcing you to give up some expressivity in terms of how you construct your predicate, and I don’t see what the benefit is

mg19:06:04

I guess it’s to support the :>> syntax which I have never seen used

seancorfield19:06:27

what would be the alternative in your view @michael.gaare?

mg19:06:47

basically the way Bravi was trying to use it

seancorfield19:06:30

So, something like:

(condq pred
  test-1 result-1
  test-2 :>> result-2)
where it calls (pred test-1), then (pred test-2) ...

seancorfield19:06:08

(since it could still pass (pred test-2) as an argument to result-2 (as a function))

mg19:06:19

Yes, something like that

mg19:06:48

Probably exactly like that

seancorfield19:06:44

Basically I just removed all the references to expr from condp...

Bravi20:06:58

btw, I always wondered why we don’t have currying in clojure

noisesmith20:06:42

currying or variable arg count, pick one

👍 12
noisesmith20:06:09

I guess there's maybe some hacky way to do both but I think it would be too clever?

Bravi20:06:45

not quite sure what is meant by variable arg count

noisesmith20:06:10

Bravi: one function can take any number of arguments

Bravi20:06:30

ah I see, yeah

noisesmith20:06:41

(+) => 0 (+ 1) => 1 (+ 1 1) => 2 (+ 1 1 1) => 3 etc.

noisesmith20:06:47

you can't really curry that

Bravi20:06:57

yeah true. I guess languages like Elm have currying by default because the functions know exactly how many args they’re going to take

pavani21:06:25

I am new to using spec. Am trying to define spec for vector of keywords. Could someone please suggest a way to do this? Sample structure

[:val1 :val2]

hiredman22:06:38

have you looked at the spec guide?