Fork me on GitHub
#clojure
<
2017-02-03
>
tbaldridge00:02:55

@schmee IIRC some more work was done in that area but the problem is that when you add more node/map types the JIT has to de-optimize the code, which can cause the gains from these new approaches to be offset by the loss in code performance.

schmee01:02:37

interesting, on that note I came across this tidbit on the clojure group while searching: https://groups.google.com/d/msg/clojure/CdeNTbeFXHU/fmMgwyc8DgAJ

schmee01:02:53

the last part is what intrigues me: >>>Since reading all that, I've often wondered how much Clojure's PersistentArrayMap might affect performance since it will probably cause many call sites to be bimorphic rather than monomorphic. I could imagine it being worthwhile to have a flag which only ever uses PersistentHashMap instead for people who really understand their workload, but I have never had time to investigate it more.

schmee01:02:40

do you know if anyone has looked into that?

thedavidmeister02:02:10

i probably just don't know enough about Java, but how do I get a NaN?

thedavidmeister02:02:19

in cljs I can just literally write NaN

thedavidmeister02:02:40

java gives me java.lang.RuntimeException: Unable to resolve symbol: NaN in this context

csm02:02:32

Double/NaN

thedavidmeister02:02:34

is this kind of code normal? #?(:clj Double/NaN :cljs NaN)

thedavidmeister02:02:59

or would people normally hide that away in a ns somewhere?

naomarik02:02:05

is there a comprehensive comparison on why someone would deploy with wildfly vs using a standalone jar?

thedavidmeister03:02:49

hmm, now i'm getting this error

thedavidmeister03:02:53

java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
 at java.math.BigDecimal.divide (BigDecimal.java:1690)

thedavidmeister03:02:08

how do i deal with that in clojure?

mfikes03:02:11

@thedavidmeister I suspect with-precision. Don’t have a repro handy

thedavidmeister03:02:38

rather light on docs

mfikes03:02:08

(with-precision 10 (/ 1.6M 9.2M))

mfikes03:02:53

without the with-precision macro, you’ll repro what you described

thedavidmeister03:02:55

is it normal for people doing clj/cljs to build up a bunch of math helpers in their projects?

mfikes03:02:09

Clojure Programming covers this, and (doc with-precision) has a bit more. IIRC it just sets *math-context* appropriately

mfikes03:02:01

I seem to only have been involved in projects that are fine with simple integer arithmetic.

thedavidmeister04:02:58

boot.user=> (with-precision 10 (/ 1.6M 9.2M))
0.1739130435M
boot.user=> (def a (with-precision 10 1.6M))
#'boot.user/a
boot.user=> (def b (with-precision 10 9.2M))
#'boot.user/b
boot.user=> (/ a b)

boot.user=> java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.

thedavidmeister04:02:09

@mfikes ^^ is certainly annoying though >.<

mfikes04:02:10

@thedavidmeister For REPL ease-of-calculation, you can set *math-context* as in

(set! *math-context* (java.math.MathContext. 10 java.math.RoundingMode/FLOOR))
and then your (/ a b) will successfully evaluate using that context.

thedavidmeister04:02:40

would that have negative consequences if i put it in an actual ns in my code?

thedavidmeister04:02:04

like, is that global, or just for the ns i write that in?

roelof06:02:36

Could something like this work :

(defn boundries 
  [pagenumber] 
  (if (pagenumber < 6) 
    range(1 - 10) 
  else (if pagenumber >= 6 and pagenumber <= 466) 
      range((- pagenumber 4) (+ pagenumber 4))
  else 
      range(460 470)))) 

<ul class="pagination">
   (for [x [(boundries)]   
        <li><a href="localhost/page?="+str(x) > x </a></li> [)
</ul>   

narendraj906:02:55

Is EDN a superset of JSON? When would things break if I replace clojure.data.json/read-str with clojure.edn/read-string?

cgrand06:02:49

And reading the same string?

cgrand06:02:05

Colons after field names. Drop them and you have some EDN.

tomaas11:02:57

hi, which library would you suggest for doing i18n? I've found tongue, which I think is really nice.

pragmatic0r12:02:20

Hi, does anyone know why I cant use CamelCase header-parameter in compojure-api, ie. 'sessionToken does not work, but 'sessiontoken works. I always get a "missing-required-key".

pragmatic0r12:02:34

@juhoteperi oh, I didnt know this, thanks for pointing this out. Is there a workaround for this ? Im mocking up an api where CamelCase parameters are used from the backend.

juhoteperi12:02:36

No workaround.

juhoteperi12:02:15

What do you mean with mocking api? When you call Ring handler with mock request, you should lowercase the headers yourself (unless you use ring-mock)

pragmatic0r12:02:37

me is working on FE stuff and I got only the swagger.json from the server team, i have no access to their server either, so im setting up based on swagger a "mock up" api

cgrand12:02:55

HTTP states header names are not case-sensitive.

juhoteperi12:02:11

Right, so the code should always use lower-case names: when accessing headers and also in Compojure-api Schema. The caller can write the name in CamelCase.

pragmatic0r12:02:36

good to know, so using CamelCase is violating any spec ? is there something that i can point the server team to ?

mpenet12:02:48

not using it, but assuming it's camelcased (or not) is.

mpenet12:02:52

I guess the ring spec specifies it needs to be downcased to play nice with middlewares

pragmatic0r12:02:08

thank you, saved me some headaches. will research this more

kudukuduppai14:02:56

adding com.datomic/clj-client "0.8.606" in Luminus project throws the following exceptionCaused by: java.lang.NoClassDefFoundError: org/eclipse/jetty/http/HttpCompliance, compiling:(qbits/jet/server.clj:183:39) at clojure.lang.Compiler.analyzeSeq(Compiler.java:6925)

henriklundahl14:02:08

You probably have some dependency issue. Try using lein deps :tree (if you're using Leiningen) to solve it.

crankyadmin15:02:36

Hi, given the below data structure, whats the best approach to add an element to the tab vector? I’m probably having a dim moment…

(def local-state (r/atom {:master-public-dns-name nil
                                         :tab-vec                               []}))

bronsa15:02:04

(swap! local-state update :tab-vec conj 1)

crankyadmin15:02:36

Thanks @bronsa, I’m clearly not having a dim moment and something else in wrong 🙂

dominicm15:02:46

Is there an implementation similar to flatten-map about, which also works on collections? My code doing it is looking very hairy.

cgrand15:02:07

@dominicm what does flatten-map do?

dominicm15:02:56

@cgrand You may recognize this code:

(defn flatten-map
  "Take a nested map (or a nested collection of key-value pairs) and returns a
   sequence of key-value pairs where keys are replaced by the result of calling
   (reduce f pk path) where path is the path to this key through the nested
   maps."
  ([f kvs] (flatten-map f nil kvs))
  ([f pk kvs]
   (mapcat (fn [[k v]]
             (if (map? v)
               (flatten-map f (f pk k) v)
               [[(f pk k) v]])) kvs)))

dominicm15:02:32

Input/Output:

(flatten-map conj [] {:OUT
              {:x 5
               :x/A 21
               :x/B 33
               :y/A 24}})
=> ([[:OUT :x] 5] [[:OUT :x/A] 21] [[:OUT :x/B] 33] [[:OUT :y/A] 24])

cgrand15:02:16

and what you’d like to do with collections use indices as keys?

dominicm16:02:10

@cgrand Yep. My solution for now has been turning collections into maps in a similar structure.

cgrand16:02:18

Do you really want to keep the "(or a nested collection of key-value pairs)” in the docstring?

cgrand16:02:23

Well actually it’s not even true atm

dominicm16:02:48

It was just what I started from 🙂, it's probably not important.

cgrand16:02:29

(defn pathify
  ([f x] (pathify f (f) x))
  ([f pk x]
    (if-some [kvs (cond
                    (map? x) x
                    (sequential? x) (map-indexed vector x))]
      (mapcat (fn [[k v]]
                (pathify f (f pk k) v)) kvs)
      [[pk x]])))

=> (pathify conj {:OUT
                  {:x 5
                   :x/A 21
                   :x/B 33
                   :y/A 24
                   :v [:a :b :c]}})
([[:OUT :x] 5]
 [[:OUT :x/A] 21]
 [[:OUT :x/B] 33]
 [[:OUT :y/A] 24]
 [[:OUT :v 0] :a]
 [[:OUT :v 1] :b]
 [[:OUT :v 2] :c])

cgrand16:02:34

I can’t quite put my finger on the source of inspiration

plins16:02:39

how can I remove the last 4 characters of a string in clojure? #(->> % (drop-last 4) (apply str)) works but it has some code smells...

bostonaholic16:02:24

(clojure.string/join (drop-last 4 %)) is probably how I'd do it

bostonaholic17:02:03

you can ->> if you prefer

jr17:02:43

(subs s 0 (- (count s) 4))

bostonaholic17:02:55

^^ I think that's less readable

bostonaholic17:02:21

works? yes. reveal intent? I don't think so

plins17:02:52

I agree the drop-last form is more readable, but is it more cpu intensive? im truncating a date so i think its ok

cgrand17:02:10

To me using sequences for simple string ops is wasteful

=> (let [s "abcdefghijklmnopqrstuvwxyz"]
     (println "drop-last")
     (quick-bench (clojure.string/join (drop-last 4 s)))
     (println "subs")
     (quick-bench (subs s 0 (- (count s) 4)))`
     (println "re-find")
     (quick-bench (re-find #"^.*(?=.{4})" s)))
drop-last
WARNING: Final GC required 46.68185951090065 % of runtime
Evaluation count : 245460 in 6 samples of 40910 calls.
             Execution time mean : 2,698571 µs
    Execution time std-deviation : 458,811034 ns
   Execution time lower quantile : 2,360011 µs ( 2,5%)
   Execution time upper quantile : 3,386236 µs (97,5%)
                   Overhead used : 2,199140 ns
subs
WARNING: Final GC required 47.18122956478963 % of runtime
Evaluation count : 7369584 in 6 samples of 1228264 calls.
             Execution time mean : 78,342042 ns
    Execution time std-deviation : 2,409232 ns
   Execution time lower quantile : 75,863069 ns ( 2,5%)
   Execution time upper quantile : 81,505076 ns (97,5%)
                   Overhead used : 2,199140 ns
WARNING: Final GC required 48.51450826533416 % of runtime
Evaluation count : 1156818 in 6 samples of 192803 calls.
             Execution time mean : 540,834427 ns
    Execution time std-deviation : 13,893766 ns
   Execution time lower quantile : 523,332106 ns ( 2,5%)
   Execution time upper quantile : 557,056296 ns (97,5%)
                   Overhead used : 2,199140 ns
nil

jr17:02:19

@bostonaholic substring is a well known operation on a string that returns a string. what is missing that doesn't declare that intent?

jr17:02:43

(drop-last 4) could be any seq

bostonaholic17:02:04

I think it's not clear that you're "dropping the last 4"

bostonaholic17:02:17

whereas drop-last 4 is very clear

bostonaholic17:02:56

(subs s 0 4) is obvious

bostonaholic17:02:20

but all that extra match muddies the water

jr17:02:20

right but we are working on strings here not seqs 🙂

jr17:02:36

no need to coerce a string to seq

joshjones17:02:28

not that anyone asked for it, but IMO the clojure.string/join makes it less clear that you want a substring, which is what subs is for

bostonaholic17:02:56

I tend to optimize for readability, and for me using subs in that way is not as readable

bostonaholic17:02:10

but this is an argument of style and readability

bostonaholic17:02:15

personal choice

bostonaholic17:02:12

if i wanted the first 4, yes I would write (subs s 0 4) and not (clojure.string/join (take 4 s))

bostonaholic17:02:27

the extra cognitive load of understanding (subs s 0 (- (count s) 4)) is too high for the benefit imo

dpsutton17:02:14

(let [from-end (- (count s) 4)]
    (subs s 0 from-end))

dpsutton17:02:32

legible and gross!

dpsutton17:02:44

i think we can all agree that we hate this, right?

dpsutton17:02:13

i'm just being melodramatic

dpsutton17:02:21

i'm a big fan of making code overly legible

dpsutton17:02:24

> Programs are meant to be read by humans and only incidentally for computers to execute

bostonaholic17:02:44

if performance is your goal, and here is a bottleneck, I'm all for optimizing for the computer

dpsutton17:02:20

i hear ya. The code i work on is almost never performance constrained so i like making it very readable

joshjones17:02:22

yes but as you said, different people find things more or less readable. clojure.string/join: Returns a string of all elements in coll subs: Returns the substring of s If I'm a programmer reading a (subs s 0 ...), I don't care how quickly I can figure out (- (count s) 4), the most important thing is that I easily identify that I'm taking a substring. It's a preference, yes, but substring of s from i to j is pretty well defined in every language, and has been in clojure since 1.0

bostonaholic17:02:18

I'm not arguing the readability or understanding of what subs does

jr17:02:39

readability is about proper naming

jr17:02:59

what's confusing about the seq approach is I don't know what that function is supposed to take as input

jr17:02:34

If I fed it (repeat "x") then it would never complete

jr17:02:02

when clearly we don't want it to be used with a lazy sequence

bostonaholic17:02:18

it wouldn't complete for your implementation either, would it?

jr17:02:28

it would throw a runtime error

lhmariano19:02:24

Hello! Could someone indicate me a good sftp library?

hiredman20:02:23

client or server? I have used apache-mina for a little sftp server a few years ago, for a little spike, it was the only reasonable ajava sftp server I could find at the time

dominicm20:02:06

(map-indexed
  (fn [i v]
    (if (= i 2)
      (inc v)
      v))
  (list 1 2 3 4 5))
Is this the best way to do update an index in a list?

dominicm20:02:46

I kinda wish I could use specter, but it's not suited for use in a library I think

shdzzl20:02:11

@dominicm Best way in what sense? What dissatisfies you about your solution?

dominicm20:02:04

@shdzzl seems like it has potential to be unperformant, I have a special version of assoc/update which knows how to interact with maps/vectors/lists

sveri21:02:06

Hi, how would I insert a json string into a json postgresql table? I get this error: column is of type json but expression is of type character varying when I try to insert a json string. So I need to convert it somehow. Is that possible using clojure.java.jdbc?

sveri21:02:29

Especially using the insert! function and not a self written sql statement.

sveri21:02:06

that little fn does the trick:

(defn value-to-json-pgobject [value]
  (doto (PGobject.)
    (.setType "json")
    (.setValue (json/write-str value))))

lhmariano21:02:56

@hiredman SFTP client! I need to send and to get a file by sftp in an application clojure!

shdzzl21:02:36

@dominicm assoc and update work on associative data structures, which lists aren't. You could improve the performance of your function by running it in a loop and counting the index, that way you can break out once you find it. Generally speaking, if you need associative behaviour, you shouldn't be using a list.

shader21:02:19

does anyone know of a decent library for generating / displaying QR codes?

shader21:02:39

In either clojure or clojurescript?

shader21:02:47

or something that would be easy to wrap in either

emccue22:02:32

If you go the global include route it seems pretty easy

shader22:02:47

@emccue thanks, I'll try that one

nooga23:02:38

I’m starting a new project that will eventually run in production. I really want to take clojure.spec for a spin but I don’t know if running beta-14 in production is a good idea. What do you think?

joshjones23:02:49

need a sticky on this -- TL;DR: it's your responsibility if it breaks, because it's alpha. But some ppl are running it in production already, and it has been very stable historically and currently seems to be so.

eggsyntax23:02:26

@alexmiller couple of tiny questions about your Clojure boot time investigation (http://dev.clojure.org/display/design/Improving+Clojure+Start+Time): 1. You have several commands of the form echo | time java -cp $CLOJURE18 clojure.main -- why are you piping the results of a bare echo into the other command? I think I'm missing something. 2. The results of your startup time poll are summarized like "30% - reported 20-30 second start times (expected: 2-5 s)" -- What do you mean by "expected"? The time you expected it to take? The time users said they expected it to take? And "expected" in the sense that that's what you/they thought would happen when they did it, or in the sense that that's the time you/they think it should be?

eggsyntax23:02:04

Some of the echo | ... commands seem to hang for me; trying to understand what's going on there so I can troubleshoot. Thanks!

Alex Miller (Clojure team)23:02:23

On 1, it's possible there was more and it got eaten in nested markup - I would have to dig out my notes. That starts a repl, which you have to kill by sending it eof

eggsyntax23:02:52

I wondered whether it was somehow sending a ^D or something.

Alex Miller (Clojure team)23:02:22

On 2, those are the results of an open poll I ran which included a way for people to express what they expected

Alex Miller (Clojure team)23:02:09

The poll ended up being not well designed due to the things I learned from reading the results

Alex Miller (Clojure team)23:02:02

So that's kind of summarizing the gist of looking at a couple hundred individual responses

eggsyntax23:02:19

Gotcha. Many thanks, a lot of interesting info in there 🙂