Fork me on GitHub
#clojurescript
<
2016-04-28
>
jimmy04:04:11

hi guys I have this problem while compiling my cljs in :simple mode : $s$$.substring is not a function. What could possibly go wrong here ?

jimmy04:04:33

and there is no error in :whitespace optimization mode

bojan.matic08:04:34

has anyone tried to do a fractal unidirectional ui architecture in clojurescript

bojan.matic08:04:07

cycle.js, for example, is looking really interesting, is there something similar in clojurescript?

bojan.matic08:04:42

i know there are libraries that emulate an elm-like architecture (which is fractal too, by the author’s definition)

mikethompson09:04:42

@bojan.matic: re-frame is one possibility, except it specifically avoids being fractal. Although there is a version called pure-frame: https://github.com/binaryage/pure-frame which is "more fractal".

mikethompson09:04:44

There's also https://github.com/jamesmacaulay/zelkova which is quite faithful to the Elm model.

mikethompson10:04:39

There's also Hoplon, which is deeply FRP-ish and which has existed since well before all the recent fuss. simple_smile

nidu10:04:33

Hello, i'm trying to compile with cljsbuild with advanced compilation on server with only 512mb RAM. Advanced compilation fails with Cannot allocate memory. When i narrow used memory with export JVM_OPTS="-Xmx256m -server" and adding :jvm-opts ^:replace ["-Xmx256m" "-server"] nothing changes (`free -m` shows 397 under free column). Is there anything i'm doing wrong or cljsbuild demands more memory?

pez10:04:00

Noob here. Has anyone tried to use the npm packaged react-sparklines in a clojurescript project? (Maybe even in a reagent project?) I don’t really know where to start… Or, I have made my project install the module in a place where the webbrowser can reach it (`resources/public` in my case) and my html file sources it. But from there I don’t know what to do.

nidu10:04:55

@pez: If the lib registers itself globally, you can use externs and foreign-libs features, see https://github.com/clojure/clojurescript/wiki/Dependencies#bundling-javascript-code.

mikethompson10:04:53

@pez see also http://cljsjs.github.io/ ... plenty of examples of rect-* components, showing how to do externs etc

pez10:04:01

Thanks, I'll check those up.

jrychter11:04:23

As a data point, for small libraries, I often found that it's easier to rewrite the functionality yourself. Especially for react libs, where there is often more coupling between the functionality in the lib and in your app. Also, some react libs have to solve problems that we in ClojureScript simply do not have, thus making the code more complicated (and consequently buggy) than necessary.

jannis11:04:15

Is there a defworker kind of macro anywhere that provides an abstraction over web workers similar to servant?

risto11:04:50

@jannis There's butler and servant

jrychter12:04:36

Should I expect go to have trouble with more complex bodies involving for or map?

dnolen12:04:29

@jrychter: yes go macro has code size issues, so does for. not sure why map would be a problem though.

bronsa12:04:10

map won't work in go blocks if the mapping function uses <! or >!

jrychter12:04:26

@bronsa @dnolen Well, it does use <!, that was the whole point of putting it in the go block. Hmm.

dnolen12:04:28

you can’t put closures into a go block with <!

jrychter12:04:55

Ok, that explains it. But that means I have to do something more clever, then.

jrychter13:04:01

I guess I'll ask then — how would you guys suggest to solve this? It was a quickly-hacked conversion of an upload function that took a single file into a function that takes many:

(defn upload! [files callback-fn]
  (go
    (callback-fn
     (into [] (keep (fn [file]
                      (let [token (:upload-token (async/<! (get-upload-token)))
                            response (async/<! (http/post "/upload" {:multipart-params [[:upload-token token]
                                                                                        ["file" files]]}))]
                        (when (and response (:status response) (>= (:status response) 200) (< (:status response) 300)) token)))
                    files)))))

jrychter13:04:06

I want to gather the results of multiple operations into a single response. Each of those operations is normally a go block.

rauh13:04:32

@jrychter: 1. Move you go into the fn, run the function (without keep, but with mapv) over the files 2. Wait until you have all results (use alts! or possibly core.async/merge) 3. Do the rest.

jrychter13:04:51

@rauh Thanks. I thought about doing this, but implementing (2) is not obvious, as this is JavaScript and you can't block. Gathering the results of multiple go blocks isn't that straightforward. But I guess I'll have to do it.

rauh13:04:35

@jrychter: There'll still be a go block further down. The one inside your fn isn't the only one

jrychter13:04:15

Right — to get the results from all the individual channels created by go blocks inside the fn.

rauh13:04:18

Ie, your mapv won't be inside one. But then your collecting part will be again.

rauh13:04:24

Common problem to collect n channels. I'm sure you'll find a function that does this somewhere

jrychter13:04:38

Ok, I got it done by writing a gathering function:

(defn- gather-results [input-channels callback-fn]
  (go-loop [channels (set input-channels)
            return-values #{}]
    (let [[v channel] (async/alts! (vec channels))
          remaining-channels (disj channels channel)]
      (if-not (seq remaining-channels)
        (callback-fn (conj return-values v))
        (recur remaining-channels (conj return-values v))))))

jrychter13:04:56

The fun part is that right now my whole uploading operation is "interestingly concurrent", but I don't even have to consider it, because of core.async.

xcthulhu13:04:23

What happens if an upload timeouts?

jrychter14:04:10

@xcthulhu: from what I understand, cljs-http will close the channel returned by http/get, which means one of the functions will close the channel and one of the gathered values will be nil.

jrychter14:04:10

At least I'm hoping that's what go does — closes the channel when the value returned by what's inside is nil.

slotkenov14:04:38

Does cljs.test have something like spies, to spy on regular js functions?

entrobe14:04:18

Is there a way to simplify (if x (f y) y)

darwin14:04:36

@entrobe: I think you can’t get much simpler than that. You could use cond-> to make it less readable simple_smile (cond-> y x f)

entrobe14:04:48

haha great thank you!

risto15:04:17

General question: how does core.async compare with the traditional callback style or observables?

risto15:04:50

It seems like frp libraries like most are purely functional by nature. Why use core.async instead of those?

darwin15:04:32

one argument could be that most other cljs libraries will use core.async, so you avoid boilerplate to bridge between your async library and their core.async

darwin15:04:19

at some point I would like to see a core.async fork which would implement "dev mode" and expose some runtime info to Dirac[1]. sometimes it is pretty hard to troubleshoot exceptions and other problems in code rewritten by core.async. that could be a pretty major advantage. any volunteers? 😉 [1] https://github.com/binaryage/dirac/issues/3

risto16:04:52

@darwin What would be an example of how it helps you avoid boilerplate when bridging other cljs libraries?

risto16:04:19

Are there any other compelling reasons to switch? I'm thinking of which one to use

darwin16:04:47

@risto well, if you have set of functions which use callbacks and set of functions which use core.async channels and you need to mix them, then you end up wrapping core.async channel operations in callbacks in one direction and calling callbacks from core.async go blocks in other direction. If all code used core.async, you would just pass channels around and use core.async primitives. I assume same problem of writing glue code will be with observables and any other library. But it is absolutely doable.

darwin16:04:01

but maybe we should move this discussion to #C05423W6H channel

darwin16:04:39

but I’m not very familiar with other async libraries/patterns, so I cannot give you general answers

darwin16:04:31

for me personally, core.async is much more pleasant to work with, than using raw callbacks aka "callback hell"

darwin16:04:38

I wrote some non-trivial amount of core.async code in dirac chrome extension (most chrome extension apis are async in nature) and it has been pleasant experience and the code reads pretty well, frankly can’t imagine how it would look using callbacks some examples of core.async heavy code; https://github.com/binaryage/dirac/tree/master/src/background/dirac/background https://github.com/binaryage/dirac/tree/master/test/marion/src/background/marion/background

risto17:04:47

@darwin: Fair enough, but I was thinking more along the lines of how it compares with FRP libraries (Observables)

risto17:04:31

I'm going to be exploring core.async anyway, I was just wondering about comparing the two

darwin17:04:24

I would definitely recommend learning core.async, even if you decided that it is not a good fit for your current task at hand, there will be probably some cool concepts to learn, and also there is a lot of code using core.async out there, so you will be able to read it comfortably

bostonaholic20:04:52

I just updated from 1.8.40 -> 1.8.51 and I get the following compile error. Has anyone seen this before? https://gist.github.com/bostonaholic/776c246b2918293d13daacf399b50fca

bostonaholic21:04:51

I’m trying to create the smallest project that will produce the error, still working on it

jr21:04:08

maybe annotated javascript in a foreign lib?

jr21:04:54

looks like that patch introduced your error

lvh21:04:35

Does anyone use bensu/doo to run tests? I’m trying to make the test failure error messages way more useful (right now you get a pile of compiled JS), I was hoping for CLJS in the failure. humane-test-output claims to do ClojureScript with no setup, but that doesn’t work; I get a wonky JS error back.

bensu22:04:55

@lvh: I think the heart of the problem is that the test reporter assumes that the error object has some fields that phantom/slimer don't

lvh22:04:28

bensu: Thanks! So this should be magically better with Karma, or does Karma also not have those fields?

bensu22:04:47

What has the fields is the underlying js env

nberger22:04:39

@bostonaholic: I've seen it, and it turned out to be a com.Google/guava dependency conflict that resulted in using guava 0.18 instead of 0.19. Resolving the dependency conflict by adding some :exclusions fixed the issue to me

nberger22:04:07

From what I remember it was a conflict on clojurescript transitive dependencies (from Reagent and something else) which pulled guava, and also from selenium libs that also pull guava

lvh23:04:13

@bensu: gotcha. So, try some other envs. Unfortunately many tests involve the DOM, but I can separate those out. Thanks!