Fork me on GitHub
#clojure
<
2017-02-07
>
richiardiandrea01:02:25

I was wondering if there is a complete pom generator for clojure out there...By complete I mean that it supports :parent, properties, distributionManagement et al?

eslachance04:02:01

:thinking_face: Let's pretend for a moment I have a bot, which receives a message that tells it to evaluate a message. My namespace in the repl is dithcord.core. Now let's pretend when I get a messsage, it basically does (eval (read-string "(str *ns*)")) . When I evaluate from the REPL I get dithcord.core as expected, but when I run it from my message "handler" I get clojure.core. I tried doing (binding [*ns* *ns*] (eval (read-string "(str *ns*)"))) but that doesn't seem to... change anything.

eslachance04:02:55

It's hard to explain exactly what's going on I admit my words fail me

eslachance04:02:05

This is a library, connecting to the Discord API. I have all this "bot" code running in memory, in the REPL, from that library's project. if that helps clarify things.

Alex Miller (Clojure team)04:02:20

are you doing anything to change the *ns* from the perspective of the handler? (like evaluating ns or in-ns etc?)

Alex Miller (Clojure team)04:02:57

the default value of *ns* is clojure.core

eslachance05:02:18

Right, but, what I mean is if I do something from the REPL which is... the same code running in memory it gives me one thing, but if it runs... hell how do I say this... "on its own" it's different

Alex Miller (Clojure team)05:02:28

the repl is doing extra work (binding *ns*) around every read/eval

Alex Miller (Clojure team)05:02:01

who is invoking it when it runs “on its own”?

eslachance05:02:25

Basically, I receive a message from a websocket (aleph) which is pushed through a couple functions that eventually call this one

eslachance05:02:45

however, I defined that function in my REPL, not in my code, so it's only "in memory" if that makes any sense

Alex Miller (Clojure team)05:02:53

I presume its in a thread that has not set a *ns*

Alex Miller (Clojure team)05:02:03

where you defined it doesn’t matter

eslachance05:02:55

Basically it's straight-up in the repl, so no I didn't define a namespace other than what it loads from my core.clj file

Alex Miller (Clojure team)05:02:02

the *ns* you’re seeing is only contextually relevant in the thread running your repl

Alex Miller (Clojure team)05:02:11

it’s a dynamic var with a per-thread binding

Alex Miller (Clojure team)05:02:23

the repl is setting it in the repl thread

Alex Miller (Clojure team)05:02:32

but that has no effect on the root binding, which is still clojure.core

eslachance05:02:46

Alright. So far I pretty much follow

Alex Miller (Clojure team)05:02:08

so you need to do something in that message handler that sets a namespace context if that’s important to you

eslachance05:02:42

I'm guessing this would be different if I was actually running code from another project which required the lib, instead of doing all this in the repl, is that correct?

Alex Miller (Clojure team)05:02:01

well, depends on the context of the thread that invokes it, so hard to say

eslachance05:02:17

Hmm. you know what let me try something real quick

eslachance05:02:46

Alright. Makes no difference if I run it from an actual project. So... the answer is, yes, I need to... "Force" a namespace, apparently, somehow

Alex Miller (Clojure team)05:02:20

it would perhaps have unintended side effects, but you could alter the root binding of *ns*

eslachance05:02:05

well, actually, here the thing is, this test I did is running code that actually has (ns dtbot.core) at the top

eslachance05:02:20

does it matter I'm just hitting "run in repl" in Cursive, like, does that alter the namespace

Alex Miller (Clojure team)05:02:23

but again, that doesn’t affect the root binding

Alex Miller (Clojure team)05:02:56

you are getting called back (I presume) from some other thread that doesn’t see the binding you’ve set in the test thread

eslachance05:02:11

Actually yes that sounds about right, it is a callback.

Alex Miller (Clojure team)05:02:49

instead of binding *ns* to *ns*, why not bind it to the namespace you want it to be?

Alex Miller (Clojure team)05:02:18

(binding [*ns* (find-ns ‘dtbot.core)] … )

eslachance05:02:29

Ah, right, that's what I was missing. find-ns

eslachance05:02:37

Think this might be it, one sec to confirm

eslachance05:02:02

Perfect! Thank you very, very much Alex, that is the little tidbit of knowledge I was missing.

qqq07:02:07

in spec, what is the idiomatic way of saying "positive float" ?

villesv07:02:27

@qqq (s/and pos? float?) ?

qqq07:02:01

@fnil: is this better than #(> % 0) because generators can recognize the "pos" ?

rauh07:02:48

@qqq It doenst look like it knows about pos?. I'd just copy the implmentation of double-in and change it to float?.

villesv07:02:36

@qqq Don't know about the generators for that (although I am pretty sure I made that work at some point) I just prefer taking the predicates apart as far as possible so spec can tell me which one failed when it does.

m3tti08:02:54

what is the best way to connect an clojure service to a soap webservice?

seancorfield09:02:45

@m3tti: I don't think there's any really good way. We looked into that a couple of years ago and ended up just using the Axis libraries directly.

seancorfield09:02:08

SOAP is just awful :(

m3tti09:02:56

@seancorfield yeah it is i don`t like it either

mrchance09:02:43

Hi, is there a chance to forbid require, use, import etc. as symbols in the ns form? I just had weird bug because a library author wrote (ns foo (import (java.lang Whatever)) instead of :import. Works at the REPL for some reason, but aot compilation failed. Looks like a bug to me

sattvik09:02:12

Well, the Clojure 1.9 alphas will notify you of that type of mistake.

mrchance09:02:49

Oh, will they? Cool! Should give that a try then

Sam H10:02:17

anyone know of a plugin that nicely formats the output from lein deps :tree?

villesv10:02:26

@m3tti I do not know of a best way, but I was recently pleasantly surprised rolling a solution by hand using http-kit, (the new) clojure.data.xml and clojure.spec. Pleasantly surprised as in not ending up having to deal with tons of unwanted tooling or complexity and in that the solution is fairly concise and readable.

m3tti10:02:50

@fnil hi i was thinking about the same solution just posting a generated xml with clojure.data.xml. now i've the problem to get wse running. But i guess i'll do it the same way

villesv10:02:53

@m3tti Cool. Where I did this we used the same methodology for a couple of integrations, but they were all fairly limited so I cannot speak for the scalability of the solution just yet. For now it seems to keep things in place quite nicely.

m3tti10:02:28

@fnil our xmls that we recieve are also quite limited with a limited amount of data. So i guess it is the best way to get the whole xml data via data.xml and doesn't hastle with java interoperability stuff

ibarrick13:02:59

I am no longer able to build my project with leiningen because maven is telling me I don't have permission to access . Is this a known issue?

dominicm13:02:31

@ibarrick You might want to do ls -las /releases/org/clojure/clojure-contrib/1.2.0-RC2/ and check the perms

ibarrick13:02:08

Sorry I left out the rest of the url

ibarrick13:02:28

that directory comes after

sophiago14:02:51

good morning. i'm running benchmarks on some functions to try and optimize them and want to make sure i'm getting accurate results as they seem a bit odd...

sophiago14:02:32

i'm using criterium and i know you generally don't want to factor in the overhead of printing things, but then i'm always concerned when i see really fast numbers and/or ones that don't grow consistent with input that i'm not realizing lazy seqs. i made that mistake when i was first learning clojure and it's pretty obvious, but this case is a bit complicated so i could just use a sanity check

sophiago14:02:40

most of the work being done is by for, which i understand to be lazy, but then i'm calling vec on it immediately so my understanding is that should realize it. i'm also running the function many times on core.async channels and storing the output in a hashmap so i would think i'm doing it correctly. it just seems exceptionally fast (breaking 1ns for fairly complicated calculation) and also i'm a bit confused as to the results of playing around with optimizing it. for example using vector-of :short rather than vanilla vectors is actually making it slower when there's nothing in my code i think could be boxing the numbers. so a bit suspicious and that's not even getting into the core.async issues

sophiago14:02:11

(the primary issue i'm seeing with core.async is calling thread rather than just putting the function directly on channels is causing it to massively slow down. this could just be because the overhead doesn't justify that but, again, not sure)

sophiago15:02:19

i'm also seeing bizarre discrepancies between just calling time and criterium's bench that make no sense to me. the former at least shows an expected slowdown when i wrap it in`doall`. so quite confused by many aspects here...

mpenet15:02:03

any code example?

sophiago15:02:32

sure. one sec (froze my repl running tests :p)

sophiago15:02:45

@mpenet i'm not sure how much the code helps on its own. do you want to see some of the benchmarks that are making me second guess myself? or for starters how would you approach getting accurate numbers?

mpenet15:02:07

no need, I just wanted to have an overview. I am not sure why you're using core async tho, you put the result of the partial-diff call into a chan to take it on the next line

bronsa15:02:27

yeah that usage of core async really doesn't make any sense

mpenet15:02:37

also vec+for could be doseq or run!

bronsa15:02:56

@mpenet neither doseq nor run! return their results

mpenet15:02:09

right, I am stupid

sophiago15:02:18

i originally was using doseq, but it wasn't playing nicely with core.async so i used a loop instead

sophiago15:02:13

and i am trying to refactor the core.async part to use a "fan-in, fan-out" pattern, but am a bit stuck on how to do it and maintain indexing of the output. it doesn't need to be sequentially returned, just stored under the correct keys

sophiago15:02:06

i have a rough version where i factor out the generator and consumer functions, but need to figure out how to propagate the idx to use as a key in the hash-map

sophiago15:02:21

and i suppose similar issue with using merge to fan-in all the input channels: they each need to pass a separate idx parameter to partial-diff and then my consumer has to know which output its getting

sophiago15:02:15

but as far as the benchmarking issue?

ghadi16:02:20

look at pipeline

sophiago16:02:14

@ghadi what does pipeline have to do with benchmarking? i'm using criterium

sophiago16:02:06

oh. thanks, but i was just answering some people's questions. i came on here to ask about benchmarking if you scroll up

eslachance16:02:57

Hmmm.... Why would (-> @session :handlers :debug) return nil but if I do (-> @session :handlers (keyword "debug")) I get ClassCastException clojure.lang.PersistentArrayMap cannot be cast to java.lang.String

eslachance17:02:54

(get-in @session [:handlers (keyword "debug")]) works though. Is this something with threading I'm not aware of?

isak17:02:13

i would call macroexpand on the expression, and i think you'll see

eslachance17:02:30

I guess I should use get-in then

rauh17:02:12

You can also use get in the last form

rauh17:02:39

(-> @session :handlers (get (keyword "debug")))

eslachance17:02:07

For consistency I think I'll use get-in since I also use it in other places I'm getting the handlers from my session

mobileink20:02:03

alexmiller: per suggestion from @seancorfield let's try this again the modern, threaded way: it would be interesting to know what peopke are using for cloud services, e.g. heroku, aws, gae, etc.

seancorfield20:02:47

Agreed. An interesting question for next year. I’ll bet AWS leads the pack tho’, with Heroku and GCP aways behind. Maybe Joyent in there too?

mobileink20:02:57

i'm under the impression that gae isn't used much, and where it is it's roll your own due to lack of good libs.

ghadi21:02:55

what was done (if anything) to correct for the user confusion about the ranking in the survey?

seancorfield23:02:54

@U0LGCREMU There’s a fair bit of work going in #google-cloud around making GAE / GCP much more Clojure-friendly.

mobileink00:02:05

i'm the boot-gae guy. ;)

amdt00:02:21

I’m interested in the large number of people using Clojurescript and deploying to the browser. I wonder what front-end frameworks and libraries are popular.

Alex Miller (Clojure team)21:02:56

sorry, didn’t see this till now (threads meh). I will make a note re cloud services, would be good to know

Alex Miller (Clojure team)17:02:07

Thanks to all for responding (and sorry on the delay in posting)

sophiago18:02:33

to put my confusion about criterium/benchmarking from earlier more succinctly (and hopefully more lucidly), the numbers i'm getting are roughly as follows: criterium 800 µs, criterium with doall 800 µs, criterium with doall and pprint5s, time 800 ns, time with doall 1.2ms, time with doall and pprint 100ms. you can see how this would be a bit baffling... it almost seems like criterium could be the problem?

joshjones18:02:55

criterium with doall is 800us, and time with doall is 1200us -- not that far off?

sophiago18:02:21

no...time is 1200ms

sophiago18:02:24

very far off

joshjones18:02:39

you said 1.2ms above

sophiago18:02:14

oh, i'm sorry my initial post was correct

sophiago18:02:34

so that's nearly a factor of 1000x

Aron18:02:05

how can i have logical xor in clojure?

sophiago18:02:42

@ashnur there's bit-xor

Aron18:02:04

i know, and that wants numbers not booleans

hiredman18:02:03

(fn [p q] (or (and p (not q)) (and (not p) q)))

sophiago18:02:51

ashnur: i'm not sure if this is the kind of thing that'd help you out, but you made me remember i recently put together a library of some bit-twiddling functions since i needed to use a number of them for a project. some are a bit buggy, but i hope to continue to work on it going forward: https://github.com/Sophia-Gold/bitwise

Aron18:02:14

ok, thanks

joshjones18:02:41

sophia, got a sample call to your diff function above?

sophiago18:02:11

actually i'm realizing i'm a bit fuzzy from sleep deprivation

sophiago18:02:31

you're right. with doall they're almost at parity

joshjones18:02:34

in your call to quick-bench be sure you reset any atoms in between, if that matters

sophiago18:02:50

i was wondering about that actually

sophiago18:02:16

i think it may be affecting running the full 60 samples since the hash-map gets so large

sophiago18:02:27

but quick-bench with doall seems the most accurate the more i think about it. a little over 1ms with a pretty intense input

sophiago18:02:35

my next question, a bit more substantial, was going to be why it's actually slower when i use vector-ofs with shorts rather than just vanilla vectors

sophiago18:02:04

i took care to make sure i wasn't boxing them in any of the calculations

sophiago18:02:28

also (sorry for all the questions) slower if i call async/thread than just putting the function on channels, but that might just mean it isn't worth the overhead

joshjones18:02:13

from what i can see in the code, you have nothing that benefits from parallelism at all -- it is a sequential process, so starting a thread only adds overhead

sophiago18:02:29

that makes sense. there's a lot to optimize with my core.async code if i can figure out how to refactor it. pipelines were suggested. i was originally trying to use merge, but couldn't figure out how to keep track of the output

joshjones18:02:30

sophiago: would be a bit faster if you remove your unnecessary put! and <!! but i know you are determined to use async

sophiago18:02:21

well, i'm thinking more i need to figure out a way to keep track of the indices without looping through sequentially. ideally i'd like to generate all the function calls with thread, use merge to put them on one input channel, and have a separate consumer

sophiago18:02:07

hmm, and you're right...i just tested it and it's about exactly the same with or without the async code the way i'm doing it now. there's nothing about it that's inherently sequential though so i bet i could speed it up significantly if i could manage to refactor it to start all the calculations at once

joshjones18:02:18

how many calculations do you have on average, approximately?

sophiago18:02:26

it's meant to scale. what i'm testing it with now is 120 times through for

sophiago18:02:35

although not all of those are concurrent. they increase exponentially. so that's three loops through with the last one being 3^4 = 81

sophiago19:02:04

i'm playing around now with keying them in the partial function so that i can just map them to threads in my generator and them merge them onto one channel

sophiago19:02:40

then maybe use a go-loop in the consumer to pull them off, store per order in the hash-map, and feed them back into the generator

sophiago23:02:02

@joshjones do you have time to give me your opinion on my attempt at refactoring that async code? it seems like i have the right idea, but i'm not sure how to go about cleaning up all the channels i create after the "fan in" part so it's throwing that comically named "ManyToManyChannel" error 😛

sophiago18:02:12

i was thinking i would benefit from something like the "fan-in, fan-out" pattern here: https://blog.golang.org/pipelines

seancorfield18:02:34

Folks, don’t forget that using threads in messages can make it easier for others to have conversations so one or two people’s problems don’t overwhelm the room...

rauh19:02:43

@hiredman FYI: this xor is easier: (def xor not=) 🙂

hiredman19:02:48

it depends what you mean by logical xor

hiredman19:02:30

and, or, etc in clojure all treat nil and false as false and anything else as true, that definition of xor doesn't do that

rauh19:02:00

@hiredman You're right, but you have to be real careful if you want thos semantics, for instance your function is not commutative

rauh19:02:40

1,nil -> true vs nil,1 -> 1

hiredman19:02:18

I could have just written it incorrectly

rauh19:02:31

Best to coerce them to bool and reduce them with not= probably.

hiredman19:02:58

no, that is logically commutative

hiredman19:02:28

1 and true are both treated as true in the system as I described it

rauh19:02:02

That's not the definition of commutative, is it?

rauh19:02:22

so unless you wrap it in a boolean it's not commutative

hiredman19:02:22

it depends, right, if you are doing clojure style logical operations, then 1 and true cannot be distinguished

rauh19:02:14

@hiredman I think this additional param to and fixed this: (fn [p q] (or (and p (not q) p) (and (not p) q)))

hiredman19:02:26

(and p (not q) p) is (and (not q) p)

hiredman19:02:50

the ways in which you could say that xor definition are not commutative are the ways in which you could say that clojure's 'or' and 'and' are not commutative, because that is what it is built out of

rauh19:02:07

@hiredman You're right doh. Though, both and and or always return an element from the input. Your original version did return true though, even though it was never given (b/c of the (not q))

seancorfield19:02:40

Note that while the truth of (and p (not q) p) and (and (not q) p) are the same, the actual values may differ:

boot.user=> (let [p nil q true] (and p (not q) p))
nil
boot.user=> (let [p nil q true] (and (not q) p))
false

seancorfield19:02:32

(which might matter if the downstream code used nil? or some?)

rauh19:02:34

@seancorfield Ah good catch, so I got it luckyly right the first time 😄

hiredman19:02:43

commutativity as a property relies on some notion of sameness, or equality, and equality is very domain dependent

nooga20:02:38

One day I got this crazy idea to host clojure atoms and core.async as an internal service, in place of a message queue, you’d just (foo/chan (foo/client “host”) “mychan") and there’s your shared channel

nooga20:02:50

Is there something like that?

eslachance20:02:35

Websockets in Aleph, with Manifolds?

eslachance20:02:43

that's pretty much what you describe

hiredman20:02:55

you could just use a message queue or message bus, of which there are a lot

nooga20:02:15

I do that, I use RMQ mostly

nooga20:02:31

and wrap their stuff with channels so usage is easy

hiredman20:02:44

if you want something that plays really nice with core.async, I would look for something that allows you to place limits on queue size

nooga20:02:25

but I don’t like the amount of configuration that comes with RMQ

nooga20:02:58

I just want channels, but over wires

devn20:02:34

What do people use for scheduling? Quartzite? Other?

devn20:02:09

Need to persistent and query jobs

hiredman20:02:09

I have, come to think of it, written 2 distributed job scheduling systems. they were very bad and worked just well enough that no one wanted to prioritize replacing them. I really hope next time I can use quartzite

hiredman20:02:30

I mean, I would almost certainly go for Quartz directly instead of with a library, but that is just me

joshjones20:02:34

we are currently re-implementing core.async channels on top of a distributed queue -- challenging so far in some respects, but looks promising

mobileink20:02:24

re:state of clojure, it would be interesting to know which cloud providers are preferred, e.g. heroku, aws, google app engine, etc.

maxfurman20:02:44

Is anyone aware of a clojure couchbase client newer than https://github.com/otabat/couchbase-clj? We need one compatible with v 2.4 of the Java client

csm20:02:18

@nooga we’re actually implementing something like that (core.async channels as a service) internally; it’s been working well so far

nooga20:02:46

@csm sounds interesting, are you actually using core.async inside? or did you just implement the interface?

hiredman20:02:50

core.async has a pretty opinionated stance on infinite queues (it doesn't have them) but I know (and have in a past life) used rabbit queues exactly like that

csm20:02:30

yeah, it’s core.async internally, basically with a simple RPC layer written with aleph and nippy

nooga20:02:13

yeah, this is pretty much what I had in mind

csm20:02:17

our use case was more one-to-one (you’re able to send a message if someone is receiving, otherwise you time out) so it’s not exactly a queue

nooga20:02:33

I’m going to prototype something like that and try on my own

nooga20:02:41

maybe learn something in the process

qqq22:02:24

in clojure spec, how do say: all vectors of three elements, where first elem = :vec2, second elem = float, third elem = float

Mikko Harju22:02:33

@qqq Do you mean like (s/cat :type (partial = :vec2) :first float? :second float?)

adambrosio22:02:32

“all vectors of three elements” sounds more like (s/every (s/tuple …))

adambrosio22:02:56

eg: [[:vec2 1.0 2.0] …] ?

bfabry22:02:25

@qqq this is what s/tuple is for

bfabry22:02:41

@qqq (s/tuple #{:vec2} float? float?)

joshjones22:02:22

yes i think he means

(s/def ::qqq (s/coll-of (s/tuple #{:vec2} float? float?) :kind vector?))
(s/valid? ::qqq [[:vec2 3.2 3.0] [:vec2 9.9 1.1]])
;; remove :kind if outer collection doesn't need to be a vector
@qqq

qqq23:02:59

I mean valid data are of the form: [:vec2 1.0 1.0] [:vec2 3.0 5.0] [:vec2 3.1415926 1.414] etc ...

qqq23:02:29

I think @joshjones has the closest solution