Fork me on GitHub
#clojurescript
<
2016-04-29
>
fasiha04:04:27

@nidu, regarding compilation 512 MB: šŸ˜®! (Sorry, I don't have any constructive advice. I learned about uberjars (including ClojureScript) so that I could build my Clojure+ClojureScript app on my beefy laptop and scp the standalone JAR to a Raspberry Pi, because the thought of compiling on that was so horrifying.)

nidu04:04:26

@fasiha: yeah, scp is a very convenient option (which i use as well eventually). I just tried to start app on dedicated server, stumbled upon multiple obstacles and had to recompile the app a lot of times. Transfering an entire uberjar each time would be cumbersome with limited traffic. Moreover i serve static independently of jar files so i still can make uberjar on server and transfer just js file.

fasiha05:04:39

(That reminds me, I should see if rsync can speed up transfer, I'm assuming for small changes the majority of the JAR is the same. But the time I spend copying is tiny compared to how long my laptop spends building the JAR and how long my target spends loading itā€¦ šŸ˜› the joys of lightweight environments)

fasiha05:04:07

Ah, static website, lovely

nidu05:04:37

No, it's not static, i just server static files with nginx so i just put resources separated from jar.

jrychter08:04:43

@fasiha, @nidu: I rsync my uberjars and see a significant speedup. Large parts of the uberjar are the same as before, so rsync is fairly speedy.

nidu08:04:34

@jrychter: that's nice! Thanks!

jimmy09:04:25

hi guys I have a problem regarding cljs build optimization. I have this eval-str function:

(defn eval-str
  [s]
  (if-not (string? s)
    (warn "s is not a string")

    (try
      (cljs.js/eval-str
       (empty-state) s nil
       {:eval js-eval}
       (fn [result] (:value result)))
      (catch js/Error e
        (debug "[eval-str]" e)))))
Same function, when I run in dev mode ( optimization ;none ) it works just fine, but when in :advanced mode, it returns nil. What could go wrong here ?

plexus09:04:30

you're using bootstrapped clojurescript? I don't think that works under :advanced compilation

jimmy09:04:14

yeah I just read the tut from cljs page

jimmy09:04:38

I don't really use boostrapped clojurescript, I do store cljs data structure as string in localcache

jimmy09:04:50

then I want to read it back as cljs data structure, that's it

jimmy09:04:33

I don't know if there is any other way, I may try transit read and write instead. Do you have any suggestions ?

thheller09:04:24

cljs.reader/read-string

thheller09:04:35

don't need eval for that

plexus09:04:51

if it's just for data then don't use eval! either use EDN or Transit

jimmy09:04:27

@thheller:, @plexus thanks you both. transit does seem to work. I will keep read-string in mind. It's good to know, thanks guys simple_smile

jrychter10:04:25

If a core.async channel isnt close!d, will it get garbage-collected?

thheller11:04:01

If you don't keep a reference to it anywhere: yes.

jrychter11:04:03

No reference. This is about channels that get a single value put into them, which causes something to terminate. I wondered if I should bother closing them.

thheller11:04:57

it would be cleaner but would not affect gc

jrychter11:04:55

Cool, thanks!

bensu13:04:25

@nxqd: google closure is in charge of :optimizations :advanced and in order for it to work it imposes some restrictions on the generated javascript. one of them is that you donā€™t use eval (which makes static analysis impossible)

bensu13:04:38

if you are not evaluating code but rather reading in data structures, use read-string or transit as suggested

fasiha14:04:17

@nxqd @thheller @plexus: here's a caveat I found with transit: if your data was generated by a non-transit JSON lib, and has strings that start with ~: tilde is a special character to transit and it won't work right:

=> (t/read (t/reader :json) "\"hi there\"")
; "hi there"
=> (t/read (t/reader :json) "\"~hi there\"")
; #object[Transit$TaggedValue [TaggedValue: h, i there]]
I was tearing my hair out why transit wasn't properly consuming data from a JSON REST API.

plexus14:04:35

So you were parsing regular json as transit? I would stick to a dedicated json parser for that

fasiha14:04:06

@plexus: Exactly right. I wrongfully interpreted @dnolen's transit blog post to mean Transit could be used as a drop-in JSON parser. Now I use transit encoders with transit decoders, and use cheshire on the Clojure-side to parse non-transit JSON. Not sure if I've needed to parse non-transit JSON on client-sideā€¦ any recommendations for that when that need inevitably arises?

plexus14:04:16

js/JSON.parse maybe? :)

plexus14:04:48

Combined with js->clj

fasiha14:04:25

@plexus: yeah. It's been a couple of years since this: ā€œYou can JSON.parse and convert to ClojureScript data structures via cljs.core/js->clj but performance is even worse than cljs.reader/read-stringā€ (http://swannodette.github.io/2014/07/26/transit--clojurescript/) but I'll profile simple_smile

martinklepsch14:04:36

Anyone aware of attempts to use Draft.js from CLJS?

xcthulhu15:04:06

@fasiha: Actually... you've only got two real options for parsing JSON to cljs AFAIK: (comp js->clj js/JSON.parse) and (comp js->clj js/eval)

xcthulhu15:04:23

Obviously eval is more dangerous

xcthulhu15:04:00

I made a little test and it gets you a tiny speedup (in Planck, so you might want to try another environment)

xcthulhu15:04:07

#!/usr/bin/env planck

(def test-data (-> (range 1000000) clj->js js/JSON.stringify))

(enable-console-print!)
(println (time (-> test-data js/JSON.parse js->clj hash)))
(println (time (-> test-data js/eval js->clj hash)))

xcthulhu15:04:32

2016-04-29 11:03:40.491 planck[40624:2161279] "Elapsed time: 2152.000000 msecs"
2016-04-29 11:03:40.492 planck[40624:2161279] -705118521
2016-04-29 11:03:42.633 planck[40624:2161279] "Elapsed time: 2141.000000 msecs"
2016-04-29 11:03:42.633 planck[40624:2161279] -705118521

fasiha15:04:47

@xcthulhu: well, I believe one can use Transit in this case, and it's 4x fasterā€”also in Planck:

(println (time (-> test-data js/JSON.parse js->clj hash)))
; 2016-04-29 11:17:47.720 planck[13328:3830409] "Elapsed time: 1206.000000 msecs"
; 2016-04-29 11:17:47.720 planck[13328:3830409] -705118521

(println (time (-> test-data js/eval js->clj hash)))
; 2016-04-29 11:18:00.564 planck[13328:3830409] "Elapsed time: 1094.000000 msecs"
; 2016-04-29 11:18:00.565 planck[13328:3830409] -705118521

(require '[cognitect.transit :as t])
(def tra (partial t/read (t/reader :json)))
(println (time (-> test-data tra hash)))
; 2016-04-29 11:17:35.435 planck[13328:3830409] "Elapsed time: 247.000000 msecs"
; 2016-04-29 11:17:35.435 planck[13328:3830409] -705118521

xcthulhu15:04:55

Awesome... TBH I didn't even know you could use transit from Planck

fasiha15:04:17

And re-reading @dnolen's post, transit is billed as a solution to parsing straight, non-Transit JSON. It's just that ~ in strings messes everything up (and maybe other things)

mfikes15:04:28

Planck itself uses Transit, so it is actually bundled in the binary

xcthulhu15:04:52

Sweet. TY for Planck btw, it's amazing

mfikes15:04:24

It is kind-of an implementation detailā€¦ but not sure how to have it be only an implementation detail, while letting users load it separately. So, for better or worse, it is there.

fasiha15:04:30

@mfikes: if I can bug you about it instead of asking Google, how come in iTerm2 and Terminal, Planck inserts 5D whenever I type Control-Left arrow?

mfikes15:04:55

By the way @xcthulhu, no need to call (enable-console-print!). I noticed that it is accidentally causing things to delegate to some Ambly code that causes it to call NSLog, which isnā€™t intended.

xcthulhu15:04:55

It's because in Terminal.app the 5D makes the terminal do a highlight of a matching paren, but it's not a console code that iTerm supports

mfikes15:04:04

@fasiha: The Line Editing keys in Planck are detailed here: http://planck-repl.org/repl.html

mfikes15:04:37

Ahh, @xcthulhu perhaps you are right. Perhaps @fasiha is seeing https://github.com/mfikes/planck/issues/119 (if so, update Planck)

mfikes15:04:11

Hop to #C0Y3CSPHQ if you have detailed questions about it

xcthulhu15:04:49

Oh yeah apparently it's gone now.

xcthulhu15:04:00

GJ šŸ˜„

xcthulhu15:04:07

Thanks again for this

dnolen15:04:29

@fasiha: was not suggesting you could in replace regular JSON parsing with Transit in the general case.

dnolen15:04:45

just that it might be worth exploring depending on the kind of data youā€™re sending over the wire - and that comment was mostly aimed at JavaScript users (many Clojure folks were already using EDN)

dnolen15:04:12

i.e. convert JSON payload to Immutable.js or whatever

fasiha15:04:54

@dnolen: got it, I initially read too much into your ā€œtransit-cljs addresses all of these issues at onceā€ā€”PEBKAC. I have seen the error of my ways šŸ˜„

dnolen15:04:47

using it to parse JSON is a pretty low value proposition

fasiha15:04:51

It was working beautifully for days, then my app broke, and I spent the usual hours digging, and realized that some idiot started a sentence with ~ šŸ˜›

dnolen15:04:58

youā€™d only get custom interpretation of JS objects and arrays and it would be slower

fasiha15:04:31

Well, above Transit chewed through JSON of a big numeric array 4x faster than js/JSON.parse.

dnolen15:04:06

well it uses JSON.parse so I donā€™t know how that is possible simple_smile

dnolen15:04:29

for ā€œequivalent" data payloads Iā€™ve seen it barely beat JSON parse only under Chrome

fasiha15:04:10

Huh, how bizarre! Just a few minutes ago: https://clojurians.slack.com/archives/clojurescript/p1461943247001501 JSON.parse vs js/eval vs transit/read shootout in Planck. 1094 vs 1206 vs 247 ms.

dnolen15:04:45

seems like youā€™re measuring js->clj and hash there

dnolen15:04:18

and yes Transit read will blow away js->clj

moxaj15:04:14

is there an equivalent of alter-var-root in clojurescript?

fasiha15:04:32

@dnolen: I think I see. To get the same equivalent output as transit/read, I do need those js->clj (and all three calls have hash), but I do see that js/eval & JSON.parse are super-fast compared to everything else. And indeed hash is painfully expensive šŸ˜®

xcthulhu16:04:53

@fasiha: If you are going to always work with ClojureScript datastructures in ClojureScript, you're pretty much always better off with transit rather than JSON.parse https://gist.github.com/bf02cc987c867520cabc4feb5c772d68

xcthulhu16:04:55

OW you should probably just stick with JSON.parse, but you'll hit other performance walls later (in particular React isn't as fast when your data is mutable)

fasiha16:04:29

@xcthulhu: indeed, I have converted everything I can into transit. And I will use JSON.parse if I need to talk to any heathen services.

jonr17:04:59

hey guys, can anyone give me tips on how to properly check for the existence of a js object from cljs?

jonr17:04:00

I have a function that emits google analytics events when in production. If in dev it just logs them locally. In staging though the Google analytics object isn't present which is breaking my app

jonr17:04:34

currently I have a (when js/ga (emit-event ...) which is erroring on the when call to js/ga

jonr17:04:56

I would have thought this is the same as (when nil ...)

jonr17:04:07

maybe an advanced compilation thing?

ddellacosta17:04:15

@jonr: last time I did this I used (when (exists? js/SomeThing) ā€¦)

jonr17:04:36

And that worked ok with an advanced compilation build?

ddellacosta17:04:49

I donā€™t know why it wouldnā€™t...

jonr17:04:08

k I'll try that, thanks!

ddellacosta17:04:22

np, hope that works

bostonaholic20:04:21

@nberger: yeah, it looks like quite a bit was added, as far as closure compiler deps, in 1.8.51 https://gist.github.com/bostonaholic/776c246b2918293d13daacf399b50fca#gistcomment-1765284

superstructor22:04:46

@jonr Iā€™ve found (some-> js/ga (emit-event ā€¦)) useful if you need to thread the thing through some forms.

superstructor22:04:22

@jonr https://clojuredocs.org/clojure.core/some-%3E%3E > When expr is not nil, threads it into the first form (via ->>), and when that result is not nil, through the next etc

jonr22:04:52

ah, very good to know. Thanks for sharing!

jonr22:04:13

And in the meantime, thanks again @ddellacosta , that worked great

jupl23:04:53

What is the best approach to say for a dev build load certain dev modules but a prod build omit dev modules and dev module calls? I know there is a closure-defines option in the Closure Compiler but what about requiring?

darwin23:04:55

@jupl: I tend to use different :source-paths for my cljsbuild dev/release configurations (assuming you are using leiningen)

jupl23:04:38

That is pretty logical.

darwin23:04:40

rel versions provide the same namespaces, but do nothing in dirac case

danielcompton23:04:32

we do the same thing