Fork me on GitHub
#clojure
<
2017-03-13
>
Alex Miller (Clojure team)00:03:33

If it's not in the spec, it's not part of the spec

Alex Miller (Clojure team)00:03:09

The code may support more than the spec

bpiel00:03:25

If I want a websocket client for clojure (ie not cljs/browser), is aleph the best option? or only option? Google isn't giving me much

bpiel00:03:48

oh.. or http.async.client?

qqq03:03:12

what's a good short hand for 'constructor' ? I don't want to use cons or const

anmonteiro03:03:21

I like to use ctor

qqq03:03:19

I like ctor now too

bostonaholic04:03:17

@qqq ‘ctor' is a pretty standard abbreviation for ‘constructor’ https://en.wikipedia.org/wiki/Constructor_(object-oriented_programming)

placeboza06:03:20

yup, and dtor as far as I know

placeboza06:03:44

for destructors

xsyn12:03:24

Is there a way for me to turn a keyword into a fn if I have function of a similar name (e.g. :and -> and) ?

genRaiy12:03:57

@xsyn maybe something like this … (symbol (name :and))

xsyn12:03:50

Yeah, I thought something like that

xsyn12:03:23

but ((symbol (name :and)) false true) => true

thegeez12:03:13

@xsyn

(resolve (symbol (name :and)))

fernandohur12:03:41

Probably a huge hack by you can do something like

(defn kw->fn [kw]
   (->> (name kw)
        (str "clojure.core/")
        (read-string)
        (eval)))

xsyn12:03:45

Tried that too

fernandohur12:03:21

user=> (kw->fn :+)
#<Fn@17b88c84 clojure.core/_PLUS_>

fernandohur12:03:46

You will need to supply the namespace where your function lives.

xsyn12:03:51

I guess I’m curious why resolve doesn’t eval

schmee12:03:53

user=> (ns-resolve *ns* (-> :+ name symbol))
#‘clojure.core/+

xsyn12:03:08

I think it’s because I’m an idiot

xsyn12:03:54

No, I’m wrong

fernandohur12:03:56

user=> (ns-resolve (symbol "clojure.core") (symbol "+"))
#'clojure.core/+

fernandohur12:03:42

Yep, looks like that one works:

user=> ((ns-resolve (symbol "clojure.core") (symbol "+")) 1 2 3)
6

schmee12:03:03

that the same as I wrote

xsyn12:03:13

So, it’s not working because and is a macro

turbopape13:03:52

Hey guys, I made a little nlp parser with some models in french - would appreciate your feed-back

joshkh13:03:45

can someone help me understand this compile error? Exception in thread "main" clojure.lang.ExceptionInfo: Call to clojure.core/ns did not conform to spec: In: [0] val: intermine.dg.repl/-main fails at: [:args :name] predicate: simple-symbol? :clojure.spec/args (intermine.dg.repl/-main) #:clojure.spec{:problems [{:path [:args :name], :pred simple-symbol?, :val intermine.dg.repl/-main, :via [], :in [0]}], :args (intermine.dg.repl/-main)}, compiling:(/tmp/form-init6404384847914733184.clj:1:294)

joshjones13:03:23

the name you gave to ns is not a simple symbol... what is the code that caused the error?

joshkh13:03:20

oh, it's :use isn't it

joshkh13:03:36

(nevermind, it's not :use...)

joshkh13:03:16

i don't see anything wrong with the ns declaration.

joshjones13:03:13

actually i think it's saying that the -main function declaration is not right, sorry about that

joshjones13:03:44

but i don't see anything wrong with that either off hand

joshkh13:03:48

yeah, i think you're right. i trimmed it down to a simple

(defn -main [& args]
  (println "Building client..."))
with no luck

joshjones13:03:17

well, I don't know what it is -- but since you posted that, maybe change the (while true) which takes 100% cpu in its time slice to something which blocks instead, to keep your main from returning. maybe @(promise)

joshkh13:03:23

okay. thanks for the advice 🙂

joshjones13:03:51

and i see nothing wrong with what you posted as far as structure -- as a sanity check, are you sure that what you posted is what's actually running to cause the error?

joshkh13:03:37

definitely not. it's someone else's code that i'm debugging. anything is possible...

qqq15:03:46

what does datomic/datascript/datalog lack that SQL has given (1) how simple datascript/datomic/datalog query language is and (2) how complicated SQL query language is?

tbaldridge15:03:22

@qqq Datomic does push you to do more work in the app code. I think that's a nice feature, but some may disagree. So in other words, SQL has fast efficient ways of sorting, grouping, etc. With Datomic you're a bit at the mercy of the developers and the language in use.

tbaldridge15:03:41

I haven't had too much of an issue with that, but doing "SELECT count(*) FROM users GROUP BY users.location HAVING count(users.location) > 10" is a bit more involved in a non-SQL db.

tbaldridge15:03:20

Personally I find that a small price to pay for all the other benefits Datomic gives you though.

qqq15:03:12

tbaldridge: (1) I'm using datascript instead of datomic, (2) I'm starting to feel another feature is datascript/datomic query feels like "the same language" since it's just EDN, whereas with SQL, even with the best bindings, it still feels like a 2nd langauge

qqq15:03:45

@tbaldridge: also, noting that your response may be biased -- how does odin & datascript compare?

qqq15:03:02

the two seems very similar in that (1) there's an eav store (2) there are indezes (3) there is a query language that is closer to datalog than core.logic

kuzmin_m15:03:54

Hi! Is anybody know workaround for this http://dev.clojure.org/jira/browse/CLJ-1625 ? I use reify with two protocols with equal method signature.

tbaldridge15:03:07

@qqq it's a question of being set-based vs lazy. Odin is a lazy query engine. Datascript and Datomic are set based, meaning they always get all the results. They are faster because of that, but your full dataset has to reside in memory. That being said, I've run a Odin-like engine on top of Datomic and it works really well.

ghadi15:03:08

@kuzmin_m Java has that same exact limitation

ghadi15:03:16

rename your protocol method is my recommendation

ghadi15:03:34

(if they are under your control)

kuzmin_m15:03:46

(ns quester.use-cases.protocols.persistence.selections)

(defprotocol Cards
  (-selections--cards [_ limit]))

(defn cards [ctx & {:keys [limit]}]
  (-selections--cards ctx limit))

kuzmin_m15:03:49

@ghadi id add ns in signature -NS—METHOD_NAME How do you think, this is ok?

ghadi15:03:17

i don't follow. I only see one protocol there

kuzmin_m15:03:14

I have the same another ns. My question about naming.

ghadi15:03:34

you'll have to rename one of them... whatever is the simplest for resolving the conflict

dpsutton15:03:43

it's not obvious what your protocol does so tough to comment on possible names

dpsutton15:03:54

but -selections--cards does seem to be pretty vague

kuzmin_m15:03:27

thanks, I’ll think

devn17:03:13

@tbaldridge Did you by any chance pass along the bug in transit-ruby mentioned the other night? The one about it having trouble reading a transit file created using multiple transit-ruby writes where Clojure's transit doesn't have a problem.

tbaldridge17:03:41

probably filing an issue is the best way to go about that, @devn, IIRC there were some issues like this in the Python version, and I think Ruby as well

tbaldridge17:03:27

basically some JSON readers assume that if you call (read-json some-stream), that they are free to read past the end of the first element. That they have full control of the stream for now on.

devn17:03:03

@tbaldridge ah, yeah, that sounds about right in ruby

devn17:03:07

the first chunk reads just fine

devn17:03:13

but then all hell breaks loose

devn17:03:27

@tbaldridge when we were talking about multiple reads, I wound up with this:

(def new (atom []))

(with-open [in (io/input-stream "file.transit")]
  (let [reader (transit/reader in :json)]
    (loop [avail? (pos? (.available in))]
      (if avail?
        (do (swap! new concat (transit/read reader))
            (recur (pos? (.available in))))
        :done))))

devn17:03:51

was that sort of what you had in mind?

tbaldridge17:03:19

yep, or just keep reading until you get an IOException

devn17:03:58

@tbaldridge yeah that felt dirty

devn18:03:11

@tbaldridge does that concat give you pause?

devn18:03:18

(sorry for 20 questions)

tbaldridge18:03:59

I'd probably use into and rework it to get rid of the atom, but that's about it.

devn18:03:13

haha yes, that's what i thought

nooga18:03:02

I tried to slap a subset of datomic’s datalog on top of sqlite and wrote somewhat clunky datalog->sql compiler, turns out it works pretty well 😄

spieden18:03:11

nice — i was thinking of making a pull expression interpreter for a nasty third party api we have to deal with

nooga18:03:52

@tbaldridge yeah, pretty much, but not exactly - it had one huge table for datoms and naively ran a ton of “recursive common table expressions" on it, pushing all the work to sqlite. I couldn’t be bothered to write any kind of unification engine, despite binge watching your youtube content 🙂

nooga18:03:11

turns out that sqlite is quite good at optimizing these things and most queries couldn’t make it sweat

lvh18:03:45

With specter, how can I do the moral equivalent of a mapcat in a transform? I’m updating a deeply nested vector, but each element will turn into some number of elements.

lvh18:03:44

I guess the obvious way to do it is with a mapcat on a selector that’s one shorter 🙂

nathanmarz18:03:28

@lvh this is the start of a navigator definition that does that:

(defnav ALL-ELEM-SEQ []
  (select* [this structure next-fn]
    (doseq [e structure]
      (next-fn [e])))
  (transform* [this structure next-fn]
    (mapcat (fn [e] (next-fn [e])) structure)    
    ))

lvh18:03:48

thanks! I’ll play with it 🙂

nathanmarz18:03:49

the transform case needs to be extended to maintain the type of the input sequence

nathanmarz18:03:05

basically it just navigates you to each element as a one-element vector

seancorfield18:03:07

@nathanmarz A question I’ve been meaning to ask you about Specter for a while: what was the motivation for the UPPERCASE naming of certain things?

nathanmarz18:03:55

I just wanted to distinguish navigators from regular functions

nathanmarz18:03:16

since functions are interpreted as filter navigators within a Specter path

nathanmarz18:03:33

for awhile it was just ALL, and then for consistency I stuck with the naming convention as I found more use cases

seancorfield18:03:52

It’s probably the thing I’ve found most jarring about Specter whenever I’ve looked at the examples… I guess it would be hard to change now...

nathanmarz18:03:13

if you want a different naming convention you can just do (def ALL <all>) or whatever

seancorfield18:03:31

Good point. I haven’t had a chance to take it for a test drive yet. It’s “on my list”.

zane18:03:17

I will be excited to hear your thoughts after you've done so, Sean.

seancorfield19:03:42

It may be a while. We don’t have the sort of data structures at work that would benefit from Specter, as far as I can see, so this will be a hobby / side project to evaluate it.

kauko19:03:55

I have a macro that throws can throw an AssertionError during expansion. I can test this expectation like this (is (thrown? AssertionError (macroexpand-1 '(my-macro)))) or (is (thrown? AssertionError (#'my-macro-impl))). Both of these pass when I run them from Cursive, but they fail when I run lein test. Any ideas?

kauko19:03:44

It doesn't throw 🙂

hiredman19:03:02

the first thing I would do, I think, would be to stop using thrown? since it isn't a thing you can check. so I would replace thrown? with something like (try whatever false (catch SomeException e true)) and then I would try that expression in different contexts

hiredman19:03:12

you mean the test reports an error

hiredman19:03:21

which isn't exactly the same thing

kauko19:03:24

I mean, the test doesn't pass

hiredman19:03:03

when you run the tests under cursive, what makes you think your test is running?

kauko19:03:31

When I run all of the tests, it says "ran 2 tests, 27 assertions". Then when I comment out the testing blocks that fail when ran with lein test, cursive says "ran 2 tests, 19 assertions".

hiredman19:03:26

that is pretty good evidence

hiredman19:03:20

Oh, what kind of assertion is this?

hiredman19:03:45

assert, clojure.spec/assert ?

kauko19:03:57

In the macro? Plain assert

hiredman19:03:13

I guess clojure.spec/assert isn't an AssertionError anyway

hiredman19:03:46

when you print out the assertion values right before the assert, when you run lein test, does it print out values that should fail?

kauko19:03:05

Let me see

hiredman19:03:15

are you disabling asserts in your project.clj? there is a dynamic var that disables them at compile time, and maybe cursive doesn't understand that

kauko19:03:08

Hmm so, the macro is basically an extended form of defn. I have a bunch of tests for it, but most of them are about actually using the macro, not just seeing if it expands properly (hope that makes sense). When I added printing before the assert that is supposed to fail, the printing works when calling the tests without expansion, but I see no printing when I run the tests that just see if the macro expands or not

kauko19:03:22

I think I explained that in the most complicated way possible 😄

hiredman19:03:24

are you aot compiling?

kauko19:03:43

I also edited one of the earlier tests to call the macro in a way that is not accepted. Now I can't run the tests in cursive or in the repl (the code doesn't compile). So I guess that means assertions do work.

kauko19:03:53

Uh, I don't know. I guess that should be in project.clj..?

hiredman19:03:10

yes, either way try blowing away target/

kauko19:03:19

appreciate the help btw 🙂

kauko19:03:08

I'll try to change the thrown? tests to something with try-catch and see if that helps

kauko19:03:17

If nothing else, to narrow down the problem

hiredman19:03:43

so if it isn't executing the println where you think it should be, you can move backward from there inserting more printlns until you find a place where code is actually getting run

kauko20:03:41

I added printing to the beginning of the macro, and even that doesn't get called

noisesmith20:03:05

to unit test a macro, don’t you need to call eval inside the test?

noisesmith20:03:12

(the expansion of a macro, that is)

hiredman20:03:44

kauko are you sure you running lein test in the same project as you are editting in cursive?

tbaldridge20:03:10

@kauko I recommend putting the macro code in a defn, and then testing the output of that defn. Debugging stuff that dies inside the compiler (as macros do) is always tough

kauko20:03:37

Yeah I know you gave me that tip before 🙂

noisesmith20:03:39

@tbaldridge that’s an excellent suggestion

kauko20:03:49

Took it to heart in some places too! 😄

tbaldridge20:03:06

lol I forget who I tell what to

kauko20:03:08

@hiredman if folder = project, then yes. If by project you mean something else, then I'm not sure 🙂

hiredman20:03:14

so you can keep putting in printlns working backwards, before each place the macro is used, till you get to a place that is actually executed

kauko20:03:31

(eval (macro-expand1 '(my-macro))) helped 😮

kauko20:03:55

Now the problem is just that when I run the test with lein test, a RuntimeException is thrown. In the cursive, it's still an AssertionError. 😄

kauko20:03:21

But thanks for the tip noisesmith! And thanks hiredman 🙂

hiredman20:03:42

it is likely an assertionerror, just sometimes eval will end up wrapping exceptions

hiredman20:03:05

if you look in the caused by stuff I bet you still find the AssertionError

kauko20:03:33

Ah no 😞

kauko20:03:02

I was wrong. Eval didn't fix the test. It was just throwing an exception on its own

kauko20:03:47

Ah well. I'll have to continue tomorrow. Or give up! 😄

kauko20:03:55

Thanks for the help everyone.

kauko06:03:31

@hiredman @tbaldridge @U051SS2EU just wanted to let you know I got it to work. The answer was (is (thrown? AssertionError (eval '()))) So pretty much like noisesmith said 🙂 Sorry for the pings!

ejelome20:03:47

hello, how do you immitate a request with a modified media-type (a.k.a mime type)? tried ...

(let [response (->
    (handler (request :get "/"))
    (content-type "text/html")
    (header "Content-Type" "text/html")
    (header "Accept" "text/html"))] ...
... but the response still returns plain/text (meaning the request sent with the mime types were ignored)

seancorfield20:03:39

I think this comes down to the middleware you’re using…?

seancorfield20:03:34

According to ring.util.response docs, you shouldn’t need to call both content-type and header “Content-Type”?

seancorfield20:03:07

So content-type adds the header as expected, calling just header “Content-Type” sets the header as expected (not shown in that screen cap — but tested in the REPL), and calling both leads to the same result — so I’m not quite sure what’s causing your issue… what exactly does your handler return @U3J70EL7K ?

ejelome12:03:47

helloe seancorfield , sorry late reply, the problem I was having is when I send a request using ring.mock.request, I simply want to alter the header sent (`"Content-Type"` in this case), so I tried each of them one by one, then finally send all of them at once, still no difference because the server still responds to plain/text, but if I access the url using a browser, it returns the correct media type (text/html). Here's the main file: https://github.com/ejelome/blog-clj/blob/master/src/blog/core.clj And here's the problematic test: https://github.com/ejelome/blog-clj/blob/master/test/blog/core_test.clj I skipped the experiment last night because I was so tired I just slept, but the main goal in the test is to send different media types (a.k.a. mime types) so I can see test and see each of their responses properly.

ejelome12:03:05

the test above btw doesn't show the problematic scenario, but just to show how I do the test

seancorfield16:03:00

You have a lot of moving parts in there — and several that I’m not familiar with (Midje, Liberator, etc) — and I’d have to read up on Ring’s mock to figure out what’s going on there. Unlikely I’ll have time to pick up all of that this week. Sorry.

ejelome18:03:59

hello seancorfield, no worries, you've already gave some great clues, thanks for the help 🙂

tbaldridge20:03:15

@kauko paste a stack trace?

tbaldridge20:03:35

or perhaps the code + stacktrace? Most of the time the stacktrace shows the truth, even if it is a bit opaque

ejelome20:03:36

Here:

... :content-type "text/html", :headers {"Content-Type" "text/plain;charset=UTF-8", "Vary" "Accept", "accept" "text/html", "content-type" "text/html"}, :status 200}

ejelome20:03:42

that's the response

seancorfield20:03:49

Perhaps a thread would be a good idea for a long, involved mostly 1:1 debugging session? Just a thought /admin-hat-on

seancorfield20:03:00

(that was odd — I shared a DropBox link in a thread, but Slack loaded the preview into the main channel… a bug in threads I think!)