Fork me on GitHub
#beginners
<
2018-10-15
>
CyberSapiens9702:10:32

Does cider have problems when using clojure 1.9 version?

dpsutton02:10:19

not that i'm aware of. what are your symptoms? @cybersapiens97

CyberSapiens9702:10:24

@dpsutton i've upgraded cider version and everything broke, now i reinstalled, lein repl command is working fine with my project on clojure version 1.9.0, but cider is saying `[WARNING] No nREPL middleware descriptor in metadata of #'cider.nrepl/wrap-version, see clojure.tools.middleware/set-descriptor!

dpsutton03:10:38

cider switches to and autoinjects newer versions of piggieback and nrepl. these were old and untouched and nrepl was contrib and stagnant. you should (TM) be able to switch any of these dependencies you might have to the nrepl or cider versions

dpsutton03:10:11

or leave them out completely and CIDER should toss them in for you

CyberSapiens9704:10:50

thanks @dpsutton i tried to re-do some changes and seems to be working

CyberSapiens9704:10:11

also, anyone knows how can i use Spec/keys in a way that i could say that a bunch of keys are going to have the same value. because i don't want to write (spec/keys [::a ::b ::c ... ::h]) and they all have the same value....

seancorfield05:10:06

@cybersapiens97 Wrap it with s/and and you can write any predicate you want to check the values.

CyberSapiens9706:10:02

thanks, i've managed to make the spec, but when the data is supposed to be (valid?) true, it throws an nullpointer exception, but when it's not (valid?) it gives me false without errors. How weird...

deg12:10:33

Is there any reason that run! does not accept multiple sequences? We can't write

(run! (fn [a b]  ...) seq-a seq-b)
Instead, we have to use
(dorun (map (fn [a b]  ...) seq-a seq-b))
or
(run! (fn [[a b]] ...)
      (map vector seq-a seq-b)
Admittedly, these are both still clear code, but still not as nice as the obvious version above.

mfikes12:10:41

In a sense, the same question could be asked of reduce

mfikes12:10:02

Andre wrote an interesting article touching on this subject https://hackernoon.com/faster-clojure-reduce-57a104448ea4

cristibalan14:10:10

Hi. Does anyone have a hint as to why (keyword "moo") gets expanded to :moo/moo after update instead of simply :moo as when it's printed just before?

(prn
  (-> {:foo "moo"}
      (update :foo (fn [e]
                     (prn "UE" e (keyword e))
                     (cond-> e
                       (string? e)
                       (keyword e))))
      (update :foo (fn [e]
                     (prn "UE2" e (keyword e))
                     [:foo e]))))
;; "UE" "moo" :moo
;; "UE2" :moo/moo :moo/moo
;; {:foo [:foo :moo/moo]}

cristibalan14:10:33

Nevermind. The (keyword e) inside the cond-> needs to be just keyword :face_with_rolling_eyes:

dadair15:10:41

Or “(keyword? e)”

dadair16:10:37

Woops, I read that wrong :) ignore!

zlrth14:10:53

i'm profiling an application using visualvm; i'd like to repeatedly run a long-running operation. the first run takes a good long time, but for the second, the results are cached, so it doesn't.

zlrth14:10:51

* i should say, it's not that i'm repeatedly running the same operation, it's that i'm running the operation, changing a thing, running it again. etc.

zlrth14:10:58

oh. cancel that. I thought caching was happening, but actually it was just a 200x speedup. simple_smile

deg14:10:46

@mfikes - Indeed, and a very interesting article, thanks. But, this really just begs the question. Andre's article shows that this is doable, but far to complex to embed in user-level code. So, the question remains: is there any good reason not to handle this in in reduce and some key core users of it, like run!?

CyberSapiens9717:10:22

I guess this would have to do with having to process two Arbitrarily large data (collections in this case). The way I’ve learned, there is 3 ways you can do this, based on the problem at hand: 1. One of the collections are dominant, therefore you don’t need to actually process the other one, so you can treat it as atomic data. 2. Both collections are about the same data and length and needs to be processed in parallel manner (I think map supports this) 3. The collections are not about the same data and length, and needs to be processed considering every type of input at each iteration. Case 1 and 2 are easy to implement, because the structure of the function is totally based on any of the collections. But in case 3, I think there lies the problems when dealing with reduce and other high order functions, because you would need to supply more base cases than it has on the structure implementation...

grierson15:10:30

What are some good resources on Data-driven/Declarative programming? I've seen Integrant and Reitit both describe themselves as data-driven and heard data > functions > macros banded about but I don't know what the benefits are.

schmee16:10:07

> Zach Tellman - Always Be Composing

orestis16:10:22

Any good guides on how to organize tests that deal with stateful external systems? E.g. setup a test db, then tear it down after all tests run.

dadair16:10:25

Not sure about guides, but per test-ns you can use clojure.test fixtures to setup a db and rollback/teardown after individual tests or once per ns

orestis16:10:26

Stuart Sierra has also written a nice thing about fixtures here: https://stuartsierra.com/2016/05/19/fixtures-as-caches

orestis16:10:52

I’m looking for similar high-level “practices” guides.

chrisulloa16:10:19

I just wrote a transducer I’m so happy with myself.

👍 4
metal 8
parrot 4
oVerde16:10:15

I have some DevOps questions about Clojure. I want to have these pre-commit configurations where on every engineers' commit it does run a couple of Lein plugins (Kibit, Yagni, Eastwood etc) My git structure has many micro projects. Had the idea to create another project just to include these plugins and run by it, BUT, this didn't work. How to make it happen?

noisesmith16:10:57

with the lein modules plugin you can use lein modules eastwood etc. https://github.com/jcrossley3/lein-modules

🙏 4
dadair17:10:29

Hello! 👋

TK17:10:03

Hi all, I'm also learning functional programming with Clojure. I did some practice on Hacker Rank functional path And created a bunch of PRs. So if anyone like to review Clojure code, it would be awesome! I'm still a beginner and feedback is always welcome 🙂 https://github.com/LeandroTk/learning-functional/pulls

noisesmith18:10:19

@TK - one quick note, (fn [n] 1), the convention is to use _ for bindings that aren't used (fn [_] 1), but in the specific case of ignoring all args and returning a constant value, there's constantly (constantly 1)

noisesmith18:10:43

in the second one, (fn [x] (f x)) can always be replaced by f

noisesmith18:10:18

so instead of (filter (fn [x] (odd? x)) coll) you get (filter odd? coll)

noisesmith18:10:48

also, filter is not a macro, despite what the 7th pr says

TK18:10:39

wow! Great.. thanks for the feedback! I will refactor it!

noisesmith18:10:29

on the 6th pr, (* (* (first original-list) 2) -1) could be replaced by (* (first original-list) 2 -1) or better yet (* (first original-list) -2)

noisesmith18:10:55

also, any loop that always consumes the next item of an input list at every step until the input list is empty should be rewritten as a reduce, since reduce always has this behavior and that makes your remaining code simpler

noisesmith18:10:11

@leandrotk100 also, for similar puzzles plus a large number of existing clojure answers to compare yours to, check out http://www.4clojure.com/

👍 4
noisesmith18:10:59

also, for the reverse function, check this out: (reduce conj () lst) - it's worth stepping through and seeing how something that concise replaces the logic of your multi line loop calls

noisesmith18:10:20

as a more advanced thing, (into () lst), since the two arg version of into encapsulates (reduce conj ...) into a single function

TK18:10:42

I learned reduce yesterday.. but it makes so much sense to me now!

TK18:10:05

I implemented a into function using reduce with conj yesterday https://github.com/LeandroTk/learning-functional/blob/master/clojure/reduce.clj

👍 4
noisesmith18:10:45

@leandrotk100 in that document you say

(conj (1 2 3) 4) --> (1 2 3 4)
- (conj (1 2 3) 4) is (4 1 2 3), (conj [1 2 3] 4) is [1 2 3 4]

noisesmith18:10:16

it's a big gotcha for when you're first learning, [] and () don't conj in the same place

Azzurite18:10:59

also (conj (1 2 3) 4) produces an error anyway as 1 is not a function

noisesmith18:10:25

right - I was being generous there, figuring that was a list that was already constructed that printed in that form :D

TK18:10:18

What is the idea behind conj for vectors and lists. Why is it different?

noisesmith18:10:41

because their internal structure is different, so the natural insertion point is different

noisesmith18:10:11

conj always attaches at the "natural" place, that is the most simple and efficient place for the data structure in question

noisesmith18:10:10

with a set or hash-map, conj might even change the order of the structure

TK18:10:29

makes sense!

noisesmith18:10:12

often your first step in a clojure algorithm is making sure your input and/or output are the best data structure for the task

noisesmith18:10:35

that's why (into () coll) acts as a reverse - linked lists build from back to front

adam19:10:26

I want to install Java on an Ubuntu machine to develop in Clojure/Leingen. Which package should I install: default-jre, openjdk-11-jre-headless or openjdk-8-jre-headless?

andy.fingerhut19:10:47

Unless you know you need jdk11 features for some reason, jdk8 is slightly better supported -- a few Clojure libraries have problems when compiled on jdk11 -- they are being updated, but there still might be a couple that trip you up out there.

andy.fingerhut19:10:16

I haven't used openjdk-8-jre-headless much myself, usually Oracle's binary release of JDK8. I believe at least some of the openjdk packages on Ubuntu may have old crypto certificates in them that can cause issues connecting via https to some servers.

adam19:10:07

@andy.fingerhut I see. I will give it a try and see if it works with my codebase. Thanks for the heads up.

yogidevbear19:10:51

What is the most idiomatic way to test for every? (not (nil?)) coll?

mfikes19:10:26

@yogidevbear (every? some? coll)

yogidevbear19:10:01

Thanks Mike 🙂 I got the same response in another channel so definitely on the right track 👍

mfikes19:10:14

Hah! Bodes well. 🙂

Mario C.20:10:30

If I make a request from Server A to Server B I get java.lang.ClassCastException: io.undertow.io.UndertowInputStream cannot be cast to java.lang.String. I can slurp the body and we are back in business. But I dont need to slurp when making a request from Client A to Server B. Any idea why this could be happening?

noisesmith20:10:48

sounds like your two requests are using different abstractions for communicating with the network

noisesmith20:10:45

a String is easier to use (no need to slurp or whatever), but it doesn't do a good job of representing data arriving over time - an InputStream allows more flexibility

Mario C.20:10:14

I am using ajax.core with the Client A and using org.httpkit.client for Server A

noisesmith20:10:00

OK, sounds like cljs in one case, clj in the other

dpsutton20:10:52

ah. just noticed subtle shift in nouns. server A -> server B. versus CLIENT A -> Server B

noisesmith20:10:58

you can give slurp a URL string if you just want a string from the remote host

noisesmith20:10:36

@dpsutton yeah I saw that too, but you can use cljs on a server or clj on a client

dpsutton20:10:10

i didn't notice until you pointed out cljs vs clj

dpsutton20:10:20

was just emphasizing it as it surprised me

Mario C.20:10:39

I dont understand. Why is the body of a request an InputStream in one and a clojure map in the other?

Mario C.20:10:19

I was under the belief that the middleware in Server B would take care of slurping the body or what have you.

noisesmith20:10:33

a middleware on a remote server can't provide a client on the other end of the network with anything but bytes

noisesmith20:10:58

any abstraction that gives you something more useful (streams, strings, hash-maps, whatever) has to be on the client side

Mario C.20:10:11

But my issue is happening on the server and not on the client

noisesmith21:10:57

"the server" is making a request, as a client, isn't it?

noisesmith21:10:51

right, so it gets bytes from another server. You could attach middleware on your http client, but that isn't there by default

Mario C.21:10:04

creating a test right now
{"field": "value"}
test here
clojure.lang.PersistentArrayMap

creating a test right now
#object[io.undertow.io.UndertowInputStream 0x356a51ab [email protected]]

Mario C.21:10:31

This is my output. First is from Client A and second is from Server A

Mario C.21:10:59

There is where my confusion lies

Mario C.21:10:22

I thought (wrap-json-body) took care of encoding the value of body to a map.

noisesmith21:10:46

is wrap-json-body somehow attached to your client?

noisesmith21:10:01

I thought it was a ring middleware attached to an http server

Mario C.21:10:12

I am confused here.

Mario C.21:10:18

From the docs The wrap-json-body middleware will parse the body of any request with a JSON content-type into a Clojure data structure, and assign it to the :body key.

Mario C.21:10:27

Which is how I understand it too

noisesmith21:10:33

OK, that's what it does when you attach it to a ring http server

noisesmith21:10:46

it's not a middleware for your http client

noisesmith21:10:51

you need something else for that

Mario C.21:10:05

I don't think I was communicating effectively the problem lol

Mario C.21:10:19

I figured out the issue though