Fork me on GitHub
#clojure
<
2017-05-12
>
wiseman00:05:37

is there a json library for clojure that gives better error messages than clojure.data.json?

rwilson00:05:12

wiseman: Not sure about error messages specifically, but I like cheshire for speed and custom extensions https://github.com/dakrone/cheshire

wiseman00:05:35

ah, thanks, cheshire seems to do (somewhat) better in that respect:

com.fasterxml.jackson.core.JsonParseException: Unexpected character ('"' (code 34)): was expecting comma to separate Object entries
                                                at [Source: java.io.StringReader@2abe9173; line: 4, column: 7]

wiseman00:05:19

e.g. it would be great to get something equivalent to

python -m json.tool config.json
Expecting , delimiter: line 4 column 6 (char 43

qqq00:05:21

(with-open [os ( "../resources/public/data.js")]
     (let [w ( os)]
       (.write w (str "var my_data = "))))
do I need to put a flush somewhere to make this work ? right now, the output file data.js is empty

rwilson00:05:48

Try this:

(with-open [w ( ( "../resources/public/data.js"))]
  (.write w (str "var my_data = ")))

rwilson00:05:21

It's a guess, but it may be that the the BufferedWriter constructed from the BufferedOutputStream isn't being flushed when the output stream is closed by with-open

qqq00:05:24

yeah, I have to use an output-stream

qqq00:05:34

I'm interleaving writing output-strea directly and using transit/writer to write out clj objects

rwilson00:05:51

It's possible that it's double buffering. Because returns a BufferedWriter even when constructed with a BufferedOutputStream

rwilson00:05:12

I'm not positive on the exact Java behavior there, but it's a suspicion

qqq00:05:56

(let [w ( os)]
       (.write w (str "var " nm " = "))
       (.flush w))
appears to work

rwilson00:05:53

Ok, so yeah with-open is only closing the output-stream, not the writer, which doesn't flush a writer constructed from that

rwilson00:05:26

Produces no output in /tmp/test:

user> (def os ( "/tmp/test"))
nil
user> (def w ( os))
nil
user> (.write w "Hello")
nil
user> (.close os)
nil
user> (.close w)
IOException Stream Closed  java.io.FileOutputStream.writeBytes (FileOutputStream.java:-2)
Produces "Hello" in /tmp/test:
user> (def os ( "/tmp/test"))
nil
user> (def w ( os))
nil
user> (.write w "Hello")
nil
user> (.close w)
nil
user> (.close os)
nil

xiongtx00:05:10

lein.test seems to always run tests alphabetically; in situations in which we spin up a single fixture for tests A, B, and C, which are stateful, this can result in tests passing when they should be failing

xiongtx01:05:08

E.g. A passes when the state is initially empty, but would fail if it’s not. However, it always passes b/c A always comes first, when the state is initially empty

xiongtx01:05:26

Is there a way to randomize the order of the tests in an ns to avoid this?

qqq01:05:48

in Java, is there a simple way to escape strings without using StringEscapeUtils (from apache)? I would prefer something that came directly with the JVM

qqq05:05:30

#(escape .... {\\ "\\\\" \" "\\\"}) ended up working fine

skylar06:05:38

I am building REST API with clojure – should I use Pedestal or Luminus?

kurt-o-sys07:05:21

https://github.com/juxt/yada - or try several ones and see which one suits your needs best. I like yada a lot 🙂

skylar07:05:47

Thanks @kurt-o-sys and @val_waeselynck, I'll check it out. What's the main differences between the two others?

curlyfry07:05:18

Perhaps just https://github.com/weavejester/compojure may be enough depending on what you want to do

kurt-o-sys07:05:26

well, to me, I pretty much like the idea of having all http methods (`GET`, POST, ...) being part of one resource - meaning, they are methods on the same url, and the code is structured as such. And there are other things as well: https://www.youtube.com/watch?v=tKFrqsFC1XM

skylar07:05:15

Another think is the OAuth2 layer – how would you guys do it?

skylar07:05:35

I was pointed to check buddy and it seems valid

skylar07:05:11

Just to secure the rest endpoints

skylar07:05:01

Seems like yada is using buddy as well 🙂

skylar07:05:03

Thannks guys

dominicm07:05:20

Yada uses buddy, yep! Feel free to come ask questions in #yada if you choose yada.

malcolmsparks08:05:04

there is fairly good OAuth2 support in yada, and it will be improved soon. There's a OAuth2 blog article for yada in the works too

malcolmsparks08:05:29

it's a good idea to get to grips with yada from the examples and docs and gradually build up your understanding of the concepts before adding the OAuth2 parts, but it's very doable (we use yada-powered OAuth2 for our http://juxt.pro website)

oskar13212:05:50

Quick question, is there a way of identifying when a dosync block fails and is retried? I would like to see that statistic for some testing I am performing.

oskar13213:05:59

after thinking carefully I think I found a way! so, because only refs are controlled by dosync atoms are perfect for this so just add (swap! sales-attempts inc) given that atoms offer atomic operations it should be safe "This is done in an atomic manner by swap! Internally, swap! reads the current value, applies the function to it, and attempts to compare-and-set! it in."

val_waeselynck13:05:53

@oskar132 you can also use a volatile instead of an atom for efficiency, I think it's safe in this case

oskar13213:05:22

@val_waeselynck that's true. In this case I'll leave it at that given that I'm only testing for correctness

noisesmith13:05:12

dosync calls do no locking, so a volatile would not be safe

noisesmith13:05:28

Unless you mean the volatile would be a local captured by the dosync call and never shared between calls

val_waeselynck13:05:00

@noisesmith yes that is what I meant

borkdude16:05:36

@robert-stuttaford and other, thanks for recommending Sentry, works like a charm

slightlycyborg18:05:35

If I want to make a symbol from a Java classname symbol and a string how would I do it

slightlycyborg18:05:03

I want Foo$Bar/baz from Foo$Bar and "baz"

noisesmith18:05:02

@slightlycyborg wouldn’t that be (symbol “Foo$Bar” “baz”) ?

uvtc18:05:27

I'd like to learn about spec, but first need a 10-thousand foot overview. Is "spec" code written alongside your regular source code, or is it separate like test code? Is there a command you run at the command line to have Clojure run spec code against your source code, or is spec something that happens during code execution? How does spec work in practice?

noisesmith18:05:41

@uvtc this is the best spec intro I’ve seen https://clojure.org/guides/spec

noisesmith18:05:30

regarding with code or separate like tests, to quote that document:

spec provides a central registry for globally declaring reusable specs

uvtc18:05:31

Thanks, @noisesmith , I'm looking at that, but it immediately goes into (s/conform even? 1000)...

uvtc18:05:51

(Urg. Not sure how to add formatted text into Slack...)

ghadi18:05:35

if you want the 10000ft overview @uvtc start with the rationale+overview before the guide: https://clojure.org/about/spec

ghadi18:05:01

it's well-worth it. spec is exciting

uvtc18:05:47

Thanks, @ghadi , missed that one. Will have a look.

bradford18:05:42

Heya. Why is this throwing a spec error?

(ns crawly.worker
  (:require
            [clojure.core.async :as async])
  (:import [core.CrawlQueue]
           [core.CrawlService]))

noisesmith18:05:58

it thinks it saw refer-clojure :as ... somewhere

noisesmith18:05:13

perhaps the version of core.async you have does this?

Alex Miller (Clojure team)18:05:22

that’s been fixed in latest core.async

noisesmith18:05:24

in fact it says clojure/core/async.clj

bradford18:05:39

Strange. It worked just a few hours ago and I haven’t updated anything in project.clj — I’m on clj 1.9.0-alpha15 and core.async 0.2.395

Alex Miller (Clojure team)18:05:19

somehow I think you have older core.async

bradford18:05:40

Oh wow, it’s been updated a lot lately. time to switch to 3.x

bradford18:05:42

Yup, that fixed it. Thanks.

wiseman19:05:05

what are your favorite clojure podcasts?

borkdude20:05:27

@wiseman Defn Podcast by @vijaykiran and @raymcdermott. Also Cognicast with various hosts.

josh.freckleton22:05:04

I have an algo that looks like it Stack Overflows in a concat portion, using a few orders of magnitude smaller of an input than I want... How do I debug and fix this?

ERROR in () (LazySeq.java:40)
expected: (= coll j)
  actual: java.lang.StackOverflowError: null
 at clojure.lang.LazySeq.sval (LazySeq.java:40)
    clojure.lang.LazySeq.seq (LazySeq.java:49)
    clojure.lang.RT.seq (RT.java:521)
    clojure.core$seq__4357.invokeStatic (core.clj:137)
    clojure.core$concat$fn__4446.invoke (core.clj:706)
    clojure.lang.LazySeq.sval (LazySeq.java:40)
    clojure.lang.LazySeq.seq (LazySeq.java:49)

...

noisesmith22:05:02

don’t call concat in an eager accumulator without realizing the lazy value it wraps

noisesmith22:05:56

that’s the usual issue - something like reduce or loop where concat is being called at every step, which builds up a really high pile of thunks, and as soon as someone finally asks for the first element, there’s too many piled up lazy ops to evaluate them all without running out of stack

noisesmith22:05:39

so pick one -either you are lazy, or you are eagerly consuming an input (usually - not knowing your code of course)

josh.freckleton22:05:57

yes, it's concat is in a loop

josh.freckleton22:05:56

so I'm only passingly familiar with optimizing against laziness and building up big thunks

josh.freckleton22:05:21

would doalling on the concat help?

josh.freckleton22:05:35

I tried that and while it doesn't SO, it's wayyy slower than I would expect

noisesmith22:05:37

yes, if you run that on every step of the loop where it concats

noisesmith22:05:55

even better is a way to build up your result without concat (may or may not make sense)

josh.freckleton22:05:15

I don't suppose apply conj is a good alternatice?

noisesmith22:05:48

(well, depends on how you want order to turn out, and how many args)

josh.freckleton22:05:57

waaaahhhhhhhhhhhhhh

josh.freckleton22:05:03

thank you thank you thank you

josh.freckleton22:05:20

I was seriously freaking out, but replacing concat with into let's me go way bigger on inputs

josh.freckleton22:05:32

etc. Thanks so much!

noisesmith22:05:40

also, into lets you use a transducer 😄

noisesmith22:05:49

glad I could help

josh.freckleton22:05:19

before 10k SO'd, now 1M works fine

noisesmith22:05:17

oh yeah, I forgot to link to that post

josh.freckleton22:05:21

thx, I'll look forward to reading that.