Fork me on GitHub
#clojure
<
2019-02-17
>
lilactown05:02:39

what’s the state of the art for setting up tests in a deps.edn project?

didibus05:02:07

Kaocha seems state of the art. For simple test running, there is test-runner from cognitec-lab

didibus05:02:28

Both have a CLI, so you.can run them from emacs in theory, but you dont have ab emacs mode or anything integrating them first class inside emacs

lilactown05:02:24

awesome! thanks

lilactown05:02:16

specifically I want something I can run from within Emacs. I’ve never bothered to set it up before :x

uosl10:02:22

I'm stuck trying to write this macro:

(ns myns.util
  (:require [herb.core :refer-macros [<class]]))

(defmacro defstyled [fn-name bindings el stylem]
  `(defn ~fn-name [~'attrs & ~'body]
     (let [body# (if (map? ~'attrs) ~'body (conj ~'body ~'attrs))
           attrs# (if (map? ~'attrs) ~'attrs nil)]
       (letfn [(~fn-name ~bindings ~stylem)]
         (into [~el (merge {:class (herb.core/<class ~fn-name attrs#)}
                           attrs#)]
           body#)))))
I want to make it so the call to <class only includes attrs# if it's non-nil. So in the above example, if attrs# is nil it should be (herb.core/<class ~fn-name) instead. I've tried many ways to do this; with a simple if or concat, but I can't get it to work.

Alex Miller (Clojure team)13:02:07

Sounds like a place where you want to unquote splice a collection instead

Alex Miller (Clojure team)14:02:41

The trick being that unquote splicing an empty collection yields nothing, not nil

uosl14:02:57

that's cool to know! sadly I get a compiler exception syntax error, and my linter tells me it's unable to resolve the symbol attrs# inside that form. could it be because attrs# is defined when the returned function is run, not the macro?

uosl14:02:39

I feel I'm a bit closer with (apply herb.core/<class ~fn-name (if (map? attrs#) [attrs#] [])) but I get Can't take value of macro herb.core/<class so I guess I'm messing up the quoting somehow?

Alex Miller (Clojure team)15:02:50

oh right, attrs# is defined inside the code you're generating so isn't available to unquote

Alex Miller (Clojure team)15:02:33

I mean you could just put an if around the call to <class in the generated code

Alex Miller (Clojure team)15:02:37

(defmacro defstyled [fn-name bindings el stylem]
  `(defn ~fn-name [~'attrs & ~'body]
     (let [body# (if (map? ~'attrs) ~'body (conj ~'body ~'attrs))]
       (letfn [(~fn-name ~bindings ~stylem)]
         (into [~el (merge {:class (if (map? ~'attrs) (herb.core/<class ~fn-name ~'attrs) (herb.core/<class ~fn-name))}
                           attrs#)]
           body#)))))

uosl21:02:05

thanks, that did the trick! by the way, I really enjoyed your book clojure applied [=

kwladyka13:02:45

Today I get an idea to focus 80% of my time on open source / documentations / tutorials , because I like make solutions for other developers. But I don’t see how I could survive doing this considering money vs contracts. I didn’t think how to monetise open source before too much. Does it make sense? Probably not 🙂 Anybody here (as a person, not corporation) make money doing mostly open source? 🙂

vemv18:02:23

Patreon is working quite nicely. Some software devs are making a proper salary out of it. Personally I donate to a handful of Patreon projects. I would mix that with a "N versions back" model. It's briefly mentioned here https://ayende.com/blog/186147-A/making-money-from-open-source-software-how-we-do-it (the author doesn't like it, I do) i.e. open-source n-versions-back releases on a continuous basis, while the latest-and-greatest release is closed-source and paid

kwladyka19:02:32

thank you for feedback

kwladyka19:02:52

Do you know anybody from Clojure community who success with it?

vemv19:02:41

Not really. Cognitect and bbatsov are only collecting a couple hundred dollars / month. But my thinking is, if you go boldly for it why would it not succeed? i.e. when you give people an incentive to use Patreon (or other), they will do it

kwladyka22:02:54

Hmm even if I will do super great tools as open source it is for free, so who will pay for that? 😉

kwladyka22:02:06

you see my concern

kwladyka22:02:50

I am afraid it is way to do things only for fun, but not as everyday job, because of money.

vemv22:02:28

I don't think many are doing n-versions-back. I'd give a think to that. Not apt for libraries, but yes for things like IDEs DBs etc

borkdude13:02:42

Nice discussion for the #off-topic channel

craftybones15:02:21

Why doesn't (doseq [f [inc dec +]] (doc f)) print doc?

Alex Miller (Clojure team)15:02:11

the symbols are being resolved to functions and doc takes symbols. quote to avoid evaluation

Alex Miller (Clojure team)15:02:59

actually since doc is a macro, you might need to do more than that to get doc evaluated with the actual symbol

craftybones15:02:14

Yeah. That didn't work 🙂

craftybones15:02:25

user=> (doseq [f `(inc)] (println f)(doc f))
clojure.core/inc

craftybones15:02:46

Hee hee. Sometimes, these things are trickier than you assume

craftybones15:02:45

clojure.repl/print-doc isn't public

keymone17:02:07

whats the best library to consume chunked/streamed http responses? something that takes a callback or returns a channel and can automatically parse json chunks

lemontea07:02:21

The closest I could get to seems to be this: https://github.com/dakrone/cheshire/issues/62 (mixing stream and laziness is confusing)…

lemontea07:02:41

As for the underlying stream itself, look like manifold is a widely supported substrate (you can convert it to other representations, such as core.async, later)… then use the client side of aleph/http-kit to read. (http-kit is old though)

lemontea08:02:41

(btw… anyone know if there’s activity in this space? my general feeling is that things almost/mostly “work”, but are not as polished as the more mainstream use case)

dottedmag18:02:45

I'd like to serialize some data structure in EDN. (spit)-ing it loses M suffix on BigDecimal objects. Is there a way to avoid that (or maybe I'm using a wrong tool?)

rutledgepaulv02:02:06

Shouldn’t you use (pr-str {:number 3M}) if you want to write edn?

dpsutton18:02:22

also works for me if i use (BigDecimal. 17)

dpsutton18:02:18

the screenshot is a split of the outputted edn file

dottedmag18:02:16

Hmm, I'm doing something wrong then.

dottedmag18:02:35

% clojure -e '(spit "foo.edn" 3M)'
% cat foo.edn
3
% clojure -e '(spit "bar.edn" {:number 3M})'
% cat bar.edn
{:number 3M}
%

dpsutton18:02:15

check str on 3 vs {:number 3M} is your issue

dottedmag18:02:35

Yes, that's different.

dpsutton18:02:02

which is what spit is calling

dottedmag18:02:31

Which is .toString on the argument.

dpsutton18:02:56

so the difference is that RT.java prints bigdecs with the M added. so if you str a map you end up here but if you just str the big dec you get the bigdec's version of what a string is

dpsutton18:02:14

else if(x instanceof BigDecimal && readably) {
			w.write(x.toString());
			w.write('M');
		}

dottedmag18:02:36

Right. Now I need to trace why it happens inside a large Clojure structure as well.

dottedmag18:02:45

Don't have a small reproducer yet.

dpsutton18:02:38

any chance you have a stringbuilder anywhere and you're building up the string yourself?

dottedmag18:02:22

Nope, I'm getting the data from API endpoint, clj-http.client passes it through cheshire, I wrap it into top-level map and spit.

dpsutton18:02:37

can json express BigDecimal? and are you sure that its coming out of cheshire correctly? Also, is perhaps cheshire doing that? are you keywordizing the keys? maybe cheshire reduces over vals and strs them manually which would exemplify this behavior

dottedmag18:02:16

JSON numbers are size-less.

dpsutton18:02:35

(reduce (fn [acc [k v]] (assoc acc (keyword k) (str v)))
        {}
        {"number" 3M})
{:number "3"}

dpsutton18:02:41

if cheshire does something like this

dottedmag18:02:41

Cheshire has a specific option, and I use it: (binding [cheshire.parse/*use-bigdecimals?* true] ...)

dottedmag18:02:13

Hmm, I wonder if clj-http has a pool inside that might interfere with that... Let me check.

dpsutton18:02:05

its kinda worrying that the string representation of BigDecimals changes on context due to RT

dottedmag18:02:07

Hah, *use-bigdecimals?* works only if the number has a decimal dot.

dpsutton18:02:29

makes sense

dottedmag18:02:55

So that's the crux of the problem, one of numbers was an integer and hasn't got converted.

dottedmag19:02:17

So I need to accept both bigints and integers down the line. Not a big deal.

dottedmag19:02:23

I would expect that str calls into RT.print (that falls back to .toString for types it does not know) instead of .toString. Perforrmance? ¯\(ツ)

dpsutton19:02:49

yeah it seems like it. but i don't know the details of pr-str vs str and print-dup and all that machinery. but i'm surprised that (str 3M) and (str {:x 3M}) are so different. It feels wrong but maybe this usage is above a simple str call

dpsutton19:02:07

hard to know if foot gun or bug

dottedmag19:02:40

I'll file a bug and we'll see.

dottedmag19:02:05

(str nil) and (str {:a nil}) are inconsistent as well.

dottedmag19:02:29

characters too.

dottedmag19:02:58

Classes too.

dottedmag19:02:25

bigints too.

dottedmag19:02:15

patterns too.

dottedmag19:02:43

Most of special cases in RT.print produce output different from their built-in .toString function.

dpsutton19:02:22

we'll see. I expect thoughtful discussion. I don't know what the conclusion of that will be.

vemv21:02:01

can I prevent commas from being printed in repl evaluations?

erwinrooijakkers09:02:25

I thought you would be able to use print-method for this to change the printing of the various types, but trying to inspect the actual object leads to a StackOverflowError for some reason:

(defmethod print-method clojure.lang.PersistentArrayMap [o ^java.io.Writer w] (.write w "changed"))
#multifn[print-method 0x41358378]
user> {}
changed
;; Trying to change the print method by using the actual object leads to StackOverflowError:
user> (defmethod print-method clojure.lang.PersistentArrayMap [o ^java.io.Writer w] (.write w (str o)))
#multifn[print-method 0x41358378]
Exception updating the ns-cache #error {
 :cause nil
 :via
 [{:type java.lang.StackOverflowError
   :message nil
   :at [clojure.lang.Var deref Var.java 197]}]
 :trace
 (...)

erwinrooijakkers10:02:51

There’s the comma

vemv10:02:46

Epic find ✌️

lemontea07:02:41

As for the underlying stream itself, look like manifold is a widely supported substrate (you can convert it to other representations, such as core.async, later)… then use the client side of aleph/http-kit to read. (http-kit is old though)