Fork me on GitHub
#clojure
<
2017-08-15
>
ghadi00:08:48

Getting to lein repl on rPi Java 8 is 28s +/- 0.5s measuring error. Getting to clojure.main repl is about 5 seconds. lein's nREPL session is noticeably laggy

ghadi00:08:36

Getting latency metrics for nREPL's RPCs would be interesting.

jaysherby00:08:20

Hey, Clojurians. Is anyone else using Walmart Labs' Lacinia GraphQL library? I'm using it but I'm having trouble understanding how the resolved-values third parameter of a resolver function signature is supposed to work. Can someone lend me a hand?

jaysherby00:08:36

By the way, I started a #lacinia channel if you'd rather take it over there.

jaysherby02:08:10

Okay, thanks, but never mind.

jaysherby02:08:44

I figured out how (non-root) field resolvers work by looking at example projects.

jaysherby02:08:26

I don't really see any good reason for them in my particular project, but they're still good to know.

seancorfield01:08:32

@ghadi What is breaking Boot on JDK 9 RC 1 right now?

ghadi01:08:38

for Boot https://github.com/boot-clj/boot-bin/pull/4 and then we'll need a release

ghadi01:08:21

(But I was talking about lein being broken earlier)

seancorfield01:08:22

Yeah, you'd mentioned both were broken and I was curious whether Boot's issue was similar to Leiningen's...

ghadi01:08:51

lein needs to remove its reliance on the bootclasspath by default. It will be 1.9+ before https://dev.clojure.org/jira/browse/CLJ-2077 lands, if that will land at all (and I don't care if it does)

seancorfield01:08:19

(I don't see us moving to Java 9 any time soon but I like to keep track of what's happening in Boot-land)

ghadi01:08:17

lein landed an option to stop mucking with the bootclasspath, but it still does it by default https://github.com/technomancy/leiningen/blob/master/bin/lein#L204-L206

fabrao02:08:35

Hello all, anyone worked with business hours calculation? I need to define something like business hour 09:00am -> 06:00pm, and local time 05:00 + 3 business hour returns 11:00pm next day. If next day is saturday or my business day (saturday can be business day for my business) return it

seancorfield02:08:03

Hmm, I'm sure someone asked that exact question a week or so ago and there was a library suggested... unfortunately that's further back than the 10k message limit @fabrao

fabrao02:08:01

@seancorfield don´t clojurians#slack has old logs repo?

fabrao03:08:57

do you remember it was here?

seancorfield03:08:19

I searched those archives but couldn't find it...

fabrao04:08:23

me too, but the difficult is the key to find it

adambard04:08:40

Just represent business hours in base 9, modulo 60b9 😛

adambard04:08:41

hour 0 is monday at 9am, hour 10 (base 9) is tuesday 9am, hour 57 is friday 4pm

adambard04:08:16

57 + 3 mod 60 = 01 = 10am monday

adambard04:08:24

(don't actually do this)

seancorfield05:08:52

Yeah, I think that was the library that was shared -- thanks @misha

henrik07:08:12

It seems that the output from explain-data of spec is not a “real” map, but some object of type #:clojure.spec.alpha. Unfortunately, it makes cheshire go nuts. How do I cast it to a plain old map?

misha07:08:24

(type (s/explain-data ...))  ;;=> clojure.lang.PersistentArrayMap
*clojure-version*
=> {:major 1, :minor 9, :incremental 0, :qualifier "alpha16"}

henrik07:08:52

What the…

chrisjd07:08:49

That's just notation for a map where all of the keys are qualified in the clojure.spec.alpha namespace.

chrisjd07:08:57

#:foo{:a 1 :b 2} == {:foo/a 1 :foo/b 2}

chrisjd07:08:58

(Introduced in Clojure 1.9)

henrik07:08:54

Oh, right!

pseud07:08:13

Anyone ever played with Alia and needed to use PagingState to basically split a larger request into separate pages ? (I should say that I see that PagingState can be passed to alia's execute function, though grepping through the source, I can't see how I'm expected to get a com.datastax.driver.core.PagingState)

mccraigmccraig09:08:15

@pseud yes - it's easy, and you don't need to directly play with PagingState

mccraigmccraig09:08:46

are the manifold and core.async implementations respectively which return a channel / stream of results and work with the PagingState in the background

mccraigmccraig09:08:14

actually, iirc they work with the ResultSetFuture/ResultSet which manage the PagingState for you

mccraigmccraig09:08:22

the :fetch-size option lets you control your page-size

pseud10:08:48

@mccraigmccraig digesting.. thanks ! 🙂

mccraigmccraig10:08:03

yw @pseud - more questions welcome should you need

hmaurer11:08:41

I have seen people use clojure.core/into to merge maps instead of clojure.core/merge. Beyond the fact that into can operate on many collection types, is there any reason to prefer one over the other when working exclusively with maps?

curlyfry11:08:30

@hmaurer I personally think it's a bit clearer to use merge when dealing exclusively with maps. merge is also variadic, letting you merge multiple maps with one call.

mpenet11:08:56

@pseud @mccraigmccraig I am on holiday, but if i recall even alia/execute supports at least :fetch-size and is truly lazy by default (no chunking). But @mccraigmccraig is right the async or manifold interfaces are much better for this kind of things

pseud11:08:11

@mpenet Yup - it returns a non-chunked lazy seq. That said, it still often seemed to cause timeouts when I issued a large query (I bound the result to a var so that the repl wouldn't try to print the response, thus realizing it). But yes, I tried :fetch-size and that seems to suffice for me. 🙂

mpenet12:08:20

The default fetch size is kinda large if I recall, that would explain the timeouts

kaspern11:08:21

Hey! Is this the right place to ask for assistance? I am new at Clojure and having some problems. I have a variable filenameswhich is a vector of filenames of .edn files.

(defn read-file-as-edn [filename]  
  (->> filename
    (slurp)
    (edn/read-string)))
 
 (let [filenames (list-files)]
  (->>      
      (map read-file-as-edn)
      (flatten)
      (into [])))
This gives an output of [], whereas what I want is the edns merged. What's wrong?

gfredericks11:08:10

@kaspern you're missing the first element of the ->> form

gfredericks11:08:31

(->> (list-files) (map read-file-as-edn) ...), and then you can get rid of the let

gfredericks11:08:46

or else (->> filenames ...)

kaspern11:08:34

(->> (list-files)
    (map read-file-as-edn)
    (flatten)
    (into []))
gives an error of java.lang.RuntimeException: Unmatched delimiter: ] , seems to be on the (->> (list-files) -line, same for the (->> filenames ...) -version

misha12:08:10

@kaspern malformed edn in one of the files

kaspern12:08:57

That would explain many things. I would have liked an error indicating so 😞 But thanks!

hmaurer13:08:16

Is there a way to get only the part of a map that matched a clojure spec? e.g. if I have (def spec (s/keys :req [:foo/bar])) and run (s/conform spec {:foo/bar 22 :abc 123}), the map does conform and so it will be fully returned

hmaurer13:08:31

I would like to only get the part of the map that conformed, and get rid of the superfluous :abc key

hmaurer13:08:22

in the more general case, I want to keep the parts of a data structure that the spec validated, and get rid of everything else

hmaurer13:08:51

Obviously I could do a select-keys afterwards if I know the keys, but I’m wondering if there is a way to do this directly from the spec

the-kenny13:08:48

I don't think it's possible, no. You could use form and match on the return value to get the keys directly from the spec and then run the select-keys on that.

octahedrion13:08:02

(defn how-conform [aspec data]
  (let [
        c (s/conform aspec data)
        c (if (map? c) c (into {} [c]))
        r (map (fn [x] (get c x x)) (s/describe aspec))
      ]
     (map vec (partition 2 (rest r)))))

octahedrion13:08:17

(how-conform (s/keys :req [::a ::b]) {::a 5 ::b 7 ::c 8})

octahedrion13:08:39

=> ([:req [:user/a :user/b]])

octahedrion13:08:26

it's not quite what you asked for but it's near

hmaurer13:08:33

follow-up question: given that the return-value of s/describe is a form, e.g.

(keys
 :req
 [:identity/first-name :identity/last-name]
 :opt
 [:identity/address :identity/user-account])
what would be the cleanest way to convert this into a map with keys :req and :opt ?

hmaurer13:08:06

e.g. given a form with named arguments, what is the cleanest way to convert it to a map where the keys are the arguments’ names, and the values are the arguments’ values?

the-kenny13:08:17

hmaurer: well you could write a tuple spec for that & conform on it. Example incoming.

the-kenny13:08:32

@hmaurer Ugh that got a bit more ugly than anticipated, but should work for any simple s/keys spec. I'm sure someone out there wrote a nicer version of this 🙂

(->> (s/describe (s/keys :req [::foo]
                                  :opt []))
              (s/conform (s/cat :keys-sym #{'keys}
                                :pairs (s/* (s/cat :kw keyword?
                                                   :keys (s/coll-of keyword?)))))
              :pairs
              (map (juxt :kw :keys))
              (into {}))

hmaurer13:08:30

thank you!

lambder13:08:44

Why the last expression returns {:a :foo, :args [{:id :XX}], :id :XX} instead of: {:a :foo, :args [], :id :XX}

(require '[clojure.zip :as zip])

(defn my-zipper [tree]
  (zip/zipper
    (fn branch? [node]
      (:args node))
    (fn children [node]
      (:args node))
    (fn make-node [node children]
      (assoc node :args (vec children)))
    tree))

(def z (my-zipper {:a :foo :args []}))

(loop [loc z]
  (if (zip/end? loc)
    (zip/node loc)
    (recur
      (zip/next 
         (zip/edit loc #(assoc % :id :XX))))))

lambder14:08:11

it looks it is associated with the fact that traversing with zip/next reveals there are 2 nodes :

(zip/node (zip/next z))                   ;  => nil
(zip/node (zip/next (zip/next z)))  ;  => {:a :foo :args []} 

lambder14:08:56

why is that? There is a single node with empty children so there should be only one node, correct?

chrisjd14:08:20

@lambder I’ve not used zippers before, but it looks like your test in branch? is slightly incorrect: that will consider a node with an :args of [] to be a branch, since it’s not nil. Changing branch? to this fixes it, by the looks of things: (fn branch? [node] (seq (:args node)))

chrisjd14:08:24

Since seq returns falsey for empty collections.

lambder14:08:25

(:args []) ;=> nil

lambder14:08:34

should it be false?

lambder14:08:16

@chrisjd (seq nil) === nil

lambder14:08:40

so what is the difference?

chrisjd14:08:16

(seq []) is also nil; that’s the key difference. I guess you would consider a node with an :args of [] to be a leaf, so it makes sense like that.

lambder14:08:43

the doc says branch? should return true for nodes with empty children as they potentially can have children

chrisjd14:08:21

Ah, so this is where my lack of experience with zippers fails us. 🙂

lambder14:08:03

for {:a :foo :args []} branch needs to be truthy

chrisjd14:08:35

Oh, my mistake — that should be children that’s modified to use seq (I actually did that in my REPL test…)

lambder14:08:29

the doc says children should return sequence of children

lambder14:08:39

the vector is itself a sequence

lambder14:08:51

(fn children [node]
      (:args node))

lambder14:08:04

returns then [] which is empty sequence of children

lambder14:08:27

where the extra nil node comes from?

chrisjd14:08:43

Well, it specifically says that it should return a “seq” of its children. A [] can be viewed as a seq, but isn’t a seq by itself.

lambder14:08:58

I havn’t said it is a seq

lambder14:08:08

i said it is a sequence

lambder14:08:18

(sequential? []) returns true

chrisjd14:08:28

Right, but the docs say seq. There’s a difference between seq and a sequence (unfortunately)

lambder14:08:10

so if i return () would that change anything?

lambder14:08:36

ok, @chrisjd it looks like this works:

(defn my-zipper [tree]
  (zip/zipper
    (fn branch? [node]
      (:args node))
    (fn children [node]
      (seq (:args node)))
    (fn make-node [node children]
      (assoc node :args (vec children)))
    tree))

lambder14:08:45

the doc is misleading tho

lambder14:08:53

nil is not a sequence

lambder14:08:07

the doc should say that if no children then return nil

chrisjd14:08:17

The key point is the distinction between a seq and a sequence. They’re not the same thing.

lambder14:08:18

instead of () or []

chrisjd14:08:28

Yeah, I agree that would be clearer 🙂

lambder14:08:35

how would you give me empty seq?

lambder14:08:47

as a literal in clojure?

chrisjd14:08:41

yeah, it’s strange, but without it things would be really awkward.

lambder14:08:42

that would be proof that seq is not sequential (sequential? nil) ;=> false

lambder14:08:54

which would be total fuckup

lambder14:08:29

seq is not a seq

chrisjd14:08:45

A seq doesn’t implement Sequential, that’s all.

chrisjd14:08:15

Err, sorry, nil doesn’t implement Sequential

bronsa14:08:47

nil doesn't implement anything, it's not a sequence and it's not sequential, it just behaves as a seq and thus as a seqable

bronsa14:08:51

the empty seq is ()

bronsa14:08:55

seq is a logical abstraction, it doesn't dictate a concrete type

lambder14:08:56

if () is empty seq the why :

(require '[clojure.zip :as zip])

(defn my-zipper [tree]
  (zip/zipper
    (fn branch? [node]
      (:args node))
    (fn children [node]
      (:args node))
    (fn make-node [node children]
      (assoc node :args (vec children)))
    tree))

(def z (my-zipper {:a :foo :args ()}))

(loop [loc z]
  (if (zip/end? loc)
    (zip/node loc)
    (recur
      (zip/next 
         (zip/edit loc #(assoc % :id :XX))))))

lambder14:08:08

gives {:a :foo :args [{:id :XX}] :id :XX}

lambder14:08:14

insted of {:a :foo :args [{:id :XX}] :id :XX} ?

lambder14:08:47

or in other words single node with empty children makes zip/next to traverse the zipper tree as if there were 2 nodes.

bronsa14:08:04

I don't have time to look at that zipper code, but arguing that () is not the empty seq is wrong

lambder14:08:20

I agree with that

bronsa14:08:24

user=> (seq? ())
true
user=> (empty? ())
true

bronsa14:08:40

clojure is not common lisp where nil == ()

lambder14:08:41

I disagreed with the statement that nil is a empty seq

bronsa14:08:39

well, nil behaves as an empty seq on seq operations, but isn't an empty seq in the sense that (seq? nil) will return false

lambder14:08:47

the zip/zipper children behaves differently on () and nil

ghadi14:08:52

i think your branch? impl needs to be (seq (:args node))

ghadi14:08:11

because if it sees nil there it will never grab the children

ghadi14:08:32

(empty list is true)

ghadi14:08:43

but (seq ()) is false

lambder14:08:53

(:args node) will return [] or () which are truthy values

lambder14:08:10

branch? should be true even if it has no children

ghadi14:08:28

i don't follow, why?

lambder14:08:49

for the doc “branch? is a fn that, given a node, returns true if can have children, even if it currently doesn’t.”

lambder14:08:11

zippers allow you edit tree

lambder14:08:36

it needs a knowledge what can have children added

lambder14:08:49

Looks like zippers have bug in seq-zip as well

lambder14:08:15

here is a question: How many nodes this zip tree has : (zip/seq-zip ()) ?

lambder14:08:00

(zip/next (zip/seq-zip ())) => [nil {:l [], :pnodes [()], :ppath nil, :r nil}] e.g. not at the end yet

lambder14:08:36

(zip/next (zip/next (zip/seq-zip ()))) => [() :end] ok after 2 zip/nexts we have reached the end

lambder14:08:24

(zip/node (zip/next (zip/seq-zip ()))) => nil

lambder14:08:31

(zip/node (zip/next (zip/next (zip/seq-zip ())))) => ()

Alex Miller (Clojure team)15:08:57

@lambder there is a ticket about this

Alex Miller (Clojure team)15:08:53

neither is quite in a state to screen (even all these years later)

Alex Miller (Clojure team)15:08:21

I’m happy to move it along if someone pays one or both of those some attention

sandbags17:08:56

anyone playing with DeepQ learning in Clojure?