This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-09-12
Channels
- # admin-announcements (3)
- # beginners (17)
- # boot (52)
- # braveandtrue (95)
- # cider (4)
- # cljs-dev (2)
- # clojars (118)
- # clojure (146)
- # clojure-art (4)
- # clojure-austin (1)
- # clojure-finland (20)
- # clojure-italy (33)
- # clojure-nl (1)
- # clojure-russia (49)
- # clojure-spec (136)
- # clojure-uk (28)
- # clojurescript (134)
- # clojutre (1)
- # conf-proposals (64)
- # cursive (3)
- # datomic (76)
- # hoplon (11)
- # ipfs (7)
- # jobs (1)
- # jobs-rus (1)
- # leiningen (4)
- # luminus (4)
- # mount (9)
- # om (34)
- # onyx (34)
- # proton (1)
- # re-frame (4)
- # reagent (35)
- # ring (2)
- # ring-swagger (6)
- # rum (15)
- # untangled (87)
I’m having some trouble compiling a clojurescript app, apparently because of a conflict in the externs, and I’m not sure what the right approach is to fix things.
I’m loading both highcharts
and javascript
as dependencies by adding them as :dependencies
from cljsjs, but both extern.js
files seem to define the $()
function.
Should I bring them into the project some other way, or should I try to munge the extern.js
files somehow? As far as I know, I need them both as dependencies, since I’m using them to draw charts in reagent
components.
Any thoughts?
I am trying to setup google sign in button in my app. Here is the javascript code for the same
gapi.signin2.render('my-signin2', {
'scope': 'profile email',
'width': 240,
'height': 50,
'longtitle': true,
'theme': 'dark',
'onsuccess': onSuccess,
'onfailure': onFailure
});
How can I pass clojurescript function names as success and failure callback for this setup?(defn ^:export on-success [] …)
and then reference it on-success
, or by fully qualified name your.namespace/on-success
How can I install the cljs-devtools? The installation page is broken here. https://github.com/binaryage/cljs-devtools
thanks @darwin
where is that table again with clojurescript versions and what features it supports?
@anmonteiro I guess it was that one. Thanks!
core.cljs:53Uncaught Error: Assert failed: creagent$core$adapt_react_class @ core.cljs:53(anonymous function) @ react_util.cljs:11
In the spirit of never asking a question and then keeping the answer secret: I was having a conflict between externs
definitions from cljsjs/highcharts
and cljsjs/jquery
, and my production build would not compile. I was asking how to resolve the conflicts.
The solution I came up with was:
1. change project.clj :dependencies
to include [cljsjs/highcharts "4.2.5-1” :exclusions [cljsjs/jquery]]
(not 100% sure why I excluded; better safe than sorry I think)
2. remove [cljsjs/jquery]
dependency
3. load jQuery from the CDN in the template
I suppose I need to ask how many JS dependencies really should ever be loaded from cljsjs
….
@bill_tozier possibly related: http://dev.clojure.org/jira/browse/CLJS-1718
@anmonteiro I will almost certainly end up bumping up against that as this prototype becomes a real product….
right, so the solution to that currently is to explicitly add one of the conflicting files to :foreign-libs
in your build under a different name
I am going through http://clojure.org/guides/spec , really awesome. I have gotten to the point on generators and I am entering in my cljs repl (s/gen int?)
, however, I get
#object[Error Error: Var clojure.test.check.generators/simple-type-printable does not exist, clojure.test.check.generators never required]
Error: Var clojure.test.check.generators/simple-type-printable does not exist, clojure.test.check.generators never required
at
@samedhi you need to add clojure.test.check
to your project and require it in that namespace
there is a note to do that in the guide too :)
I’m not 100% sure that step is identical in cljs though and would be happy to take a PR or pointer on how to improve it
I did fail to add it to the namespace (since this is clojurescript), let me give that a shot.
yeah, prob need to mention that
(:require cljs.pprint [cljs.core.async :as async :refer [<! timeout]] [cljs.spec :as s] [cljs.spec.impl.gen :as gen] [om.core :as om] [om.dom :as dom :refer [div video source track]] [om-tools.dom :include-macros true])
@samedhi you still aren’t requiring clojure.test.check
, AFAICT
here’s an example in the CLJS compiler codebase: https://github.com/clojure/clojurescript/blob/master/src/test/cljs/cljs/spec_test.cljs#L5
@anmonteiro: Sad, I can’t believe I just did that twice.
any example how to iterate native js array in a tight loop? loop
is pretty close but I still have to use seq
fist
and next
, would like to see it compiled into a javascript for loop
@darwin FWIW you can use seq
, first
and next
/`rest` in JS arrays
ah right
re-reading the question, I didn’t understand it at first
What are the plans for cljs.spec going forward? Slightly confused by the fact that spec is in alpha for JVM Clojure but in regular 1.9 for cljs. Will there be a point in time after (JVM) Clojure 1.9 is released and spec is finalized that clj.spec and cljs.spec will work the same (at least with regards to API)?
just for context, I’m working on a library which will allow you to aget
a path from nested #js objects, I generate static code when possible, but when I hit a dynamic case, I need to do it at runtime, and I want that routine to be as fast/low-level as possible
cljs.user=> (def x #js [1 2 3])
#'cljs.user/x
cljs.user=> (while (pos? (.-length x)) (println "element: " (first x)) (.shift x))
element: 1
element: 2
element: 3
nil
maybe an option?
note that mutates the array
good first step, I will use aget
to index it directly without mutation, and avoid first
, thanks
@anmonteiro ended up writing this[1], it generates pretty barebone #js loop with no calls to core[2]: [1] https://github.com/binaryage/cljs-oops/blob/295b8f0b9bc903fbef6e01d08f299993da20f97a/src/lib/oops/core.clj#L106-L134 [2] https://gist.github.com/darwin/57fe51dd382660382eaa3cc453caa317
we recently bumped our clojurescript version from 1.7.228 to 1.9.229. However, we found a change in behavior and I’ve narrowed down the change to the jump from 1.7.228 to 1.8.34:
@uwo probably https://github.com/clojure/clojurescript/commit/817b44d34795696eda473776e355fb956d3aa5ae
oh that’s not in the gap you mentioned
@uwo hrm I think that might be worth opening a JIRA ticket
not for opening tickets
btw it seems related to get
, not get-in
cljs.user=> (get "lol" nil)
"l"
@uwo hold on before opening a ticket, confirming one thing
OK go ahead, definitely a bug
here’s the culprit too: https://github.com/clojure/clojurescript/commit/3373567df77b6a83386458ea0dd0854ed4ffe20e
(int nil)
in a JS environment is 0 🙂
@uwo happy to work on a fix tonight too
bbiab
@anmonteiro given https://github.com/clojure/clojurescript/wiki/Reporting-Issues, should I create a minimum reproduction, or would just a code snippet suffice?
@uwo don’t worry about that, just provide a description. I know what it is and will get to it tonight anyways 🙂
my code snippet above could potentially be a minimal repro if you want
@anmonteiro is this sufficient? http://dev.clojure.org/jira/browse/CLJS-1775
@uwo: looks good
@anmonteiro thanks for the help!
Hi guys. Hopefully simple question: I'm doing some HTML canvas drawing from CLJS. Let's say I have a vec of values, and I'd like to run a canvas lineTo(x,y)
call for each entry in the vec, where x is the index and y is the value at that index. The vec might have tens of thousands of entries, and I'd like to do this drawing at 60fps, so perf is a bit of an issue. What would you suggest as the fastest way to run through the vec and call a side-effectful function for each entry?
I've played a bit with a while loop using an atom to track the current index (imperative af, I know)... and also using a map-indexed seq with dorun (which performs a little worse than the while loop).
For reference:
(dorun (map-indexed render-fn values)) ; Using dorun, or...
(while (< @i n-values) (render-fn @i (nth values @i)) (swap! i inc)) ; Using a while loop
I've stripped some unimportant details, so forgive any apparent weirdness. This is just to outline the two approaches.@exupero I will try doseq. 1 sec.
I tried this:
(doseq [i (range) :while (< i n-values)] (render-fn i (nth values i)))
I don't think that's quite right, though..
Actually, that seems to work. But that has about the same perf as dorun — much (much) worse than while.
I'm working on the modern-cljs tutorial and have a brepl running. Thing is, it doesn't evaluate my multi line input. Just "#_=>" after the last line. I'm here: https://github.com/magomimmo/modern-cljs/blob/master/doc/second-edition/tutorial-05.md#brepling-with-the-shopping-calculator and "1.00" doesn't appear.
@exupero Ah. Good idea. The swap
call is the largest source of overhead to that approach. Also, when using doseq or dorun, there's about a 50ms GC pause every few seconds, which totally blows my 60fps 😞
@ivanreese you can try using a js array instead of vector and write a loop
Yeah.. dropping down to JS is my last resort. I'm using this as an opportunity to learn more about the perf characteristics of CLJS. I expect (hope) that there will be ways to "go fast" in CLJS, and I'm keen to find them.
@exupero switching to while + volatile has seemingly made a sizeable improvement.
@jr I'll try loop/recur now
the trick for good performance will be allocating a js array (instead of vector) for the values and then loop using the aget
operation on that js array
Is there an equivalent to conj / push?
Or do I need to get the count, then aset?
I'm playing with this on the REPL and it seems count works, but I haven't found any other collection fns that do.
I wonder why (count my-js-arr) works..
Ah. Now I see.
(cond (array? coll) (alength coll))
Boom 🙂
hello people, I'm trying to implement error reporting on my a node.js app, so I'm pushing the error object into a external service, the only problem now is that the stack goes into .js form, which is not that helpful. is there an way to source map stack traces for clojurescript on node.js?
@wilkerlucio as long as you’re enabling sourcemaps in your cljs build, then you should be able to use https://github.com/evanw/node-source-map-support to get node to be aware of them
(you can do it manually without that package if you need to as well, if so that package should be a good jumping off point on how to do it yourself)
@tanzoniteblack: thanks for the feedback, I tried the node source map, but it doens't seems to be working, I added the package to my app, and added the .install
command on the top of my execution, still seeing the old stack, did I missed something?
@wilkerlucio , you also verified that there is a sourcemap outputted by your cljsbuild, right?
(just covering basics, first)
and also did the
//# sourceMappingURL=path/to/source.map
bit to tell the library where your sourcemap is located?@jr loop/recur seems about as fast as the volatile while loop — at this point, I'd need to disable some other parts of my system to really get a sense of how they compare. One curiosity: the render-fn
was being created with partial
(so that I could pass more arguments to it when it was being used with map-indexed). When I switched to loop/recur, performance absolutely cratered.. until I switched back to using the real fn, rather than the partially applied version. Looking at the call stack, it seemed the partial'd fn was being re-created on every loop!
@tanzoniteblack yes, they are there. it seems that some portion is translated, I get stacks like these (even before using the node-source-map-support
package):
@uwo attached a patch to your issue. Could potentially be included in the next version of ClojureScript
@ivanreese you’re right about partials. They are very slow in a tight loop
I know that anonymous functions are better there but isn’t it even better to create the function outside of the loop and just call it?
The call to partial
was outside the loop.
(let [render-fn (partial render-history ctx)]
(loop [i 0]
(when (< i n-values)
(render-fn i (aget values i))
(recur (inc i)))))
That's a bit simplified — render-history takes a whole bunch of args. Looking at the implementation of partial, it seems if you're passing a lot of args, it ends up using apply
and concat
behind the scenes, so that might lead to the slowdown.
In any case, I only needed the partial
when I was using seq-based loops. Since I'm going to stick with either the while+volatile+js-arr, or the loop/recur+js-arr.. I don't need the partial. It was just.. surprising.
I’ve been drilling down and learning the details about performance so all of this is very interesting for me.
Cool. Yeah, it's going to be a big focus for me, since 90% of the work I do needs to run at 60fps. (games, simulations, procedural art/music, etc)
Yeah, I imagine. I spent 13 years doing .NET and the solution there was mainly just to throw more hardware at it. Heh.
And of course all the basic level stuff like knowing when to use sprocs vs. LINQ or writing good looping algorithms and such.
Yeah. I'm going to enjoy finding the right balance between (lovely) immutable CLJS, and (works fine, just not as delightful) mutable JS.
I'm sure there'll be some super tight-loop/low-level code that I won't be able to hoist up into CLJS-land. But if I can find ways to use the superpower of immutability to just utterly skip doing work that doesn't need to be done, that'd be the most ideal. Finding it.. will be the challenge.
My render times are now dominated by browser APIs rather than CLJS core fns. Thanks for the help @exupero, @jr, and @akiva!
I tend to use the cljs compiler as a source of inspiration for performance tips. Good luck!
Like, reading the output of the compiler? Or reading the source of the compiler?
Ah, yeah. I look forward to doing a lot of source-diving on CLJ(S). I'm just still getting a handle on the basics of the language.