Fork me on GitHub
#clojurescript
<
2017-11-10
>
tkolleh05:11:03

I’m attempting to read a line from stdin for NodeJS. The JS code would be something like:

var readline = require('readline');
process.stdin.setEncoding('utf8');
var rl = readline.createInterface({
  input: process.stdin,
  terminal: false
});
rl.on('line', readLine);
function readLine (line) {.....}
Whats the approach for reading a line in cljs? Any best practice for reading stdin using nodeJS and clojurescript? I translated that to this with no luck:
(def readline (js/require "readline")) ;;require nodejs lib
(def process (js/require "process"))
(.setEncoding process.stdin "utf8")
(def rl (.createInterface readline {
                                    :input process.stdin
                                    :terminal false}))
(.on rl "line" readline)

rauh05:11:53

@tkolleh You should use #js{...} instead of {} to get JS object instead of a clj map

borkdude06:11:47

What does this mean: > Backing this one out, goog.string.format defies advanced optimization https://dev.clojure.org/jira/browse/CLJS-324

borkdude07:11:16

We use gstring/format with advanced compilation and it works, but maybe I’m missing something

tkolleh07:11:03

@rauh Thanks i’ve made the update. I am still working to get the code to work with nodeJS as a single js file:

(ns hello-world.core
  (:require [clojure.string :as string] [cljs.nodejs :as nodejs]))
(nodejs/enable-util-print!)
(defn -main [& args]
  (let [readline (js/require "readline")
        rl (.createInterface readline js/process.stdin js/process.stdout)]
    (.on rl "line" 
         (fn [line]
              (def lineVector (clojure.string/split line #" "))
              (if  (and (< (get lineVector 0) 10) 
                            (< (get lineVector 1) 10))
                (+ (get lineVector 0) (get lineVector 0)))))))
(set! *main-cli-fn* -main)

thheller07:11:26

you should turn (def lineVector (clojure.string/split line #" ") into a let. def should only be used at the top-level, never nested like this.

tkolleh08:11:43

@thheller Thanks, for simplicity sake i’ve removed all of that and replaced it with (fn [line](println line)) I believe the issue is that one of the functions is not getting loaded. I’ll do a closer analysis.

TypeError: a.Zb is not a function
    at Function.$d.w (.../main.js:209:47)

thheller08:11:53

you could use :optimizations :simple instead of :advanced when you are starting out

tkolleh08:11:40

@thheller 😀 wow you are too cool for school 😎 that was it I changed to :optimizations :simple and was able to input stdin.

tkolleh08:11:50

Many thanks

risto12:11:46

whats the usual compile time for lein figwheel?

thheller12:11:34

that varies greatly depending on each project

risto12:11:39

i'm wondering if i have it incorrectly setup, it takes like a couple of minutes to compile like a hello world thing. I don't remember it being like that before

risto12:11:51

like the simplest hello world

thheller12:11:00

thats too long indeed

risto12:11:41

Successfully compiled "[]" in 83.072 seconds.

thheller12:11:02

don’t know much about figwheel but maybe setting :verbose true and :compiler-stats true will provide some insight?

risto12:11:29

ah thanks, i'll try it out

risto12:11:17

i dont think it's a figwheel thing

risto12:11:54

it lags at Compiling blah from [blah]...

risto12:11:01

and then it prints out a bunch of stuff it compiled

risto12:11:34

actually it looks like it's figwheel:

[risto@miniarch src]$ time lein cljsbuild once backend-dev
Compiling ClojureScript...

real    0m12.402s
user    0m15.432s
sys     0m0.521s

risto12:11:55

i dont remember it taking anywhere near that long before though, maybe like 20 seconds or something for the jvm

mfikes13:11:33

@borkdude My guess is that using goog.string.format in the standard library is not amenable to DCE. Everybody's final artifact grows by about 1200 bytes uncompressed, 480 bytes compressed, regardless of whether you make use of the capability.

borkdude14:11:03

@mfikes Thanks. So it makes sense to switch to https://github.com/funcool/cuerdas for this?

mfikes14:11:16

@borkdude I suppose that’s up to you. If you actually make use of goog.string.format, in your code, then perhaps 480 bytes is worth it. (I don’t know how many bytes would be added if you just used cuerdas.core/format) Checking…

mfikes14:11:06

@borkdude Adding cuerdas as a dep and simply making a call to cuerdas.core/format adds 47 KB unzipped and 19 KB zipped. Perhaps there is some stuff in that library that is not amenable to DCE.

mfikes14:11:51

I agree, that can't be explained by the small amount of code involved in cuerdas.core/format.

mfikes14:11:58

Checking again, but by pasting only cuerdas.core/format code directly in the mix. (I think it might be because it pulls in edn/read-string.)

mfikes14:11:33

@borkdude By manually pasting in cuerdas.core/format and all of the functions it depends on, things grow by only 723 bytes uncompressed, 359 bytes compressed. But, by then simply adding [cuerdas.core] to my :require vector (without actually using any functionality in it) causes it to explode back out by 47 KB / 19 KB. So there is something in the cuerdas library that is not amenable to DCE.

borkdude14:11:12

ok, thanks for checking this out 🙂

mfikes14:11:19

@borkdude I think I've isolated it to this being pulled in, regardless of whether you want it https://github.com/funcool/cuerdas/blob/master/assets/xregexp/xregexp.js

borkdude14:11:03

that’s not so great then

borkdude14:11:23

@mfikes I added your comments to this thread. If you don’t want it there, I can remove it: https://www.reddit.com/r/Clojure/comments/7bo9ro/funcoolcuerdas_the_missing_clojurescript_string/dpmdoei/

mfikes14:11:32

Yeah, it is unfortunate that there is no good way to only pull in that foreign lib for the 4 or 5 functions that use it. 😞

mfikes14:11:43

Coarse-grained DCE, if you will.

borkdude14:11:46

Maybe the new npm stuff can do it?

juhoteperi14:11:02

Yes, new npm stuff could do it, but only if no lib in app uses foreign libs

borkdude14:11:43

hmm, I guess it’s not so nice to force transitive npm deps onto your users as a library

borkdude14:11:58

I don’t know if that’s even possible

juhoteperi15:11:33

It is, deps.cljs in a library can define :npm-deps and if app uses :install-deps true, those get installed automatically

juhoteperi15:11:53

Though not sure if that is very good idea

borkdude15:11:33

I guess if it’s possible, it’s only a matter of time before people start doing that

mfikes15:11:15

If I maintained cuerdas, I'd be motivated to take that foreign lib and somehow make it compatible with Closure or re-write it in ClojureScript.

borkdude15:11:53

I’m going to file an issue, see what their thoughts are about it

thheller15:11:05

AFAICT almost everything in cuerdas uses that foreign-lib

mfikes15:11:17

I don't have experience targeting the web, but I would expect 19 KB is a lot

borkdude15:11:07

@mfikes What is your main target? Mobile?

borkdude15:11:01

Isn’t that the same problem over there?

mfikes15:11:20

In mobile, the main concern (IMHO), is launch latency. And :advanced is good for that. For example an app might take 2 seconds to launch with :advanced instead of 3 with :simple on an old device. Library size drives how fast things can be parsed upon launch, so a lot of the same concerns crop up, but to a much lesser import, I suppose.

mfikes15:11:32

Yes @thheller I can see that my previous estimate of 4 or 5 functions is wrong

borkdude15:11:22

Speaking of DCE, how does clojure.test.check do? I need a seedable RNG in my clojurescript

mfikes15:11:31

Aren't the entire React and ClojureScript deps up around 30 KB each. (Just thinking about how big 19 KB is relative to other things.)

borkdude15:11:38

in production code that is, not in test

borkdude15:11:16

@mfikes Yes, but React is not something I would do without, funcool/cuerdas is totally optional

mfikes15:11:09

@borkdude My initial reaction to you clojure.test.check is to try it and see if DCE works. For example Om had an unintentional bloat, for which there is a ticket. The best way to find out is to try 🙂

borkdude15:11:36

yeah, will do

borkdude15:11:39

thanks 🙂

borkdude15:11:34

Adds around 14kb for me

gfredericks15:11:37

is that a lot?

gfredericks15:11:51

it has to use goog.math.Long

gfredericks15:11:49

also if 14kb is bad, you might try it again with master -- somebody added a patch that changes the cljs rng code

borkdude15:11:11

Not sure if it’s bad, but I only need some basic functionality that might be provided by other smaller libs

borkdude15:11:16

Just adding the require or removing it also differs 706 bytes. Not sure why that is

borkdude15:11:41

I was wrong, only 3 kb, I guess that’s fine

borkdude15:11:06

How mature is the npm support in clojurescript right now — is it roughly finished/production ready or still being worked on?

mfikes18:11:04

@borkdude In a recent podcast (CaSE), right near the very end, David estimated that it may be another year before the current rapid evolution in the ClojureScript tooling and JS ecosystem integration aspects settle down. I'm not directly involved in the NPM stuff, but if I had to guess, he was thinking along the lines of your question when he made that statement.

risto18:11:25

how does the new es6 stuff in clojurescript transpile? is it still using the closure compiler to do that or is it babel?

mfikes18:11:10

@risto I haven't heard of any support for Babel

borkdude18:11:03

How cool, that podcast with David. I listened to the one with Alex recently.

Orco18:11:54

I just listened to the same podcast and ended up here 🙂

borkdude18:11:44

I was actually waiting for the episode of defnpodcast with David, but Joy Clark beat them to it 😉

zalky20:11:24

Hi, is there any easy way to figure out where the cljs compiler is spending most of it's time when compiling?

mfikes21:11:48

@zalky Run a conventional JVM profiler

zalky21:11:02

@mfikes, hmm... I've done a little profiling of Clojure with JVM profilers (yourkit, jvisualvm) in the past and wasn't always straight forward to me how to map JVM objects to Clojure ones. Do you think it would be possible to see which namespaces objects are taking up most of the compilers time?

mfikes21:11:20

@zalky Usually if there is a hotspot, while it is not straightforward to map things, I've found it relatively clear where the system as a whole is spending its time. This usually involves some digging, of course, oftentimes looking at both the ClojureScript and Clojure compiler's source.

mfikes21:11:28

@zalky Are you trying to find general performance issues that the compiler is exhibiting with your codebase? Or are you just trying to see if you have a particular namespace or two that it taking all of the time?

zalky21:11:53

@mfikes the later, I think.

zalky21:11:56

I've been building out a new project, and just pulled in a number of dependencies and while the compile time is within the realm of expectations, I was hoping it would be faster, and I wanted to see if either one of the dependencies I've pulled in is taking more time, or if maybe there's some obvious way I could speed it up.

mfikes21:11:02

If you add :verbose true you can visually watch for any huge pauses while it is compiling to see if any namespace sticks out

zalky21:11:01

K, thanks, that's also a quick and easy thing to try.

dpsutton23:11:32

i'm using transit in cljs and running into transit specific uuid's when i'm expecting uuids. the problem is that transit uuid's seem to fail uuid? and blow up when calling uuid on it as it fails the string check. has anyone worked around this in the past?