Fork me on GitHub
#clojurescript
<
2016-11-28
>
cmath02:11:07

(let [svg-root (.-ownerSVGElement (.-target e))] (. js/console log e) (. js/console log svg-root) (set! (.-onclick svg-root (fn [_] (println "* yay we can overwrite"))))) I get an error of: Unknown dot form of (. svg-root -onclick ((fn [_] (println "* yay we can overwrite")))) What is going on here?

cmath02:11:29

(when something happens on an inner svg element, I want to overwrite the handler on the root svg element)

danielcompton03:11:16

Is there a way to use a goog-define in a ClojureScript macro for the purposes of DCE?

danielcompton04:11:03

The question above as phrased doesn't make sense, as the goog-define is 'injected' after macro compilation has taken place. The answer I came up with is to put the goog-defined value inside the macro templated code, and let the Closure Compiler to eliminate it

rauh07:11:43

@danielcompton You just need to make sure that you tell cljs that the var is a boolean, otherwise it'll wrap it in truth_ calls and Closure wont DCE it.

urbanslug08:11:02

and know where the compiled CSS ends up?

magnars08:11:50

@urbanslug It ends up in memory, served by the process. If you want it on disk, use the export utilities.

urbanslug08:11:16

magnars ha! what a pleasure finding you here

urbanslug08:11:33

One sec let me figure out if it’s caching. We have changes reflecting locally but not on staging servers

urbanslug09:11:11

Hey, so I can see the compiled scss to css files but I can’t quite see the single css file e.g styles.css number 7 here https://github.com/magnars/optimus#usage

urbanslug09:11:48

Isn’t there meant to be a single style.css file on disk also?

magnars09:11:26

ah, that isn't quite clear in that part of the readme. All bundles are served under /bundles/

magnars09:11:13

so you'll find that under /bundles/styles.css - but don't use that directly, you'll want to use the cache busted version as served by optimus' link namespace.

urbanslug09:11:13

Ok let me read that

urbanslug09:11:22

Thanks for your help so far

jell09:11:28

I saw @mfikes benchmark of reduce compared to C (https://www.youtube.com/watch?v=LopU-kMpe8I&amp;feature=youtu.be) and played with it locally and it worked and was awesome, BUT I noticed that (reduce + 0 (range 1E7)) runs in 10ms where (reduce + (range 1E7)) runs in 500ms, while (reduce + (lazy-seq (range 1E7))) also runs in 10ms. I checked the implementation and noticed that while (reduce + 0 (range 1E7)) runs a tight loop, without the init value it falls back to ci-reduce which is inefficient for range (it’s calling nth on the range at each iteration which should be super inefficient)

jell09:11:55

I think that’s a perf bug?

rauh09:11:49

@jell nth of Range just does some math.

jell09:11:13

yeah but every time you call nth you recompute all the intermediate values

rauh09:11:16

But not sure, why -reduce of range doesn't just call (f) itself and do a faster reduce

rauh09:11:09

No you don't recompute the intermediate values. Check the Range deftype

rauh09:11:50

(nth (range 1e29) 1e28) is O(1)

jell09:11:12

really… ok didn’t know that cool

jell09:11:23

still seeing a massive slowdown compared to wrapping the range in a lazy-seq, so I guess my analysis is wrong but the observation still holds?

rauh09:11:56

I agree, somebody more familiar shoudl chime in why -reduce of Range doesn't call seq-reduce or even just itself

jell09:11:13

ok yeah I see that nth and count are O(1), but they still do a bunch of math that’s unnecessary in that loop https://github.com/clojure/clojurescript/blob/01149751ae129ab01f5d427a48c5cedae9386f64/src/main/cljs/cljs/core.cljs#L8897-L8915

urbanslug09:11:40

@magnars Thanks, there was an issue with the scss 😄 you helped us find it.

mhuebert11:11:31

Does anyone know offhand why the keys :doc, :file, :arglists, :line, :end-line, :column, :end-column for a def are duplicated in the cljs compiler state, under both the def itself and also within its :meta key? eg. the value of (get-in @cstate [:cljs.analyzer/namespaces ‘cljs.core :defs ‘rand-int]) contains all of the keys above, as well as a :meta key where those keys/vals are duped

thheller12:11:23

@mhuebert chaos 😉 .. there are quite some oddities that piled up over the years

thheller12:11:13

hopefully we will spec all of that data out at some point

dnolen14:11:17

@mhuebert there’s no particular reason - it just means in the compiler emission for :var-special we don’t need to figure anything out - it could easily be done differently

dnolen14:11:03

@jell it probably doesn’t matter to the JS VM since some of those checks are loop invariant

jell14:11:08

@dnolen I am seeing a major slow-down though? the diff between (reduce + (range 1E7)) and (reduce + (lazy-seq (range 1E7))) is 50x (granted, + is probably the cheapest reduction step one can have)

dnolen14:11:35

@jell why do you think there should be a huge difference there?

jell14:11:36

(using planck)

jell14:11:44

because I ran it 😛

jell14:11:59

oh you mean if I did the analysis

dnolen14:11:01

I don’t recommend going down any benchmarking rabbit holes

dnolen14:11:19

run a profiler and it will become obvious

dnolen14:11:24

(how they are different)

jell14:11:26

I mean even between (reduce + 0 (range 1E7)) and (reduce + (range 1E7))

dnolen14:11:04

read the source, run a profiler and you will see why

dnolen14:11:17

if you have a broader questions as to whether we care … the answer is “no"

jell14:11:10

yeah that was my original question if that was a perf bug

jell14:11:30

my naive reading of the code led me here as well

dnolen14:11:15

it’s nice that @mfikes (higher order) case competes with an imperative loop - but this isn’t the kind of case we spend much time on

jell14:11:15

thank you for taking the time, and I understand your time is precious 🙂 if you don’t mind me asking, why are we not using ci-reduce for both reduce cases on range if we do not care about this kind of optimization? (if the answer is more than a 10s thing forget it and I’ll try to figure it out later)

jell14:11:18

(also really not trying to be annoying just very curious, sorry if I’m bothering)

dnolen14:11:31

because we copied implementation approaches over from Clojure when we ported all the transducers stuff

dnolen14:11:53

just like we tend to do when we port things over

jell14:11:09

oh ok sorry then I see

dnolen14:11:27

(none if this is to say if you have small perf patches we won’t take them)

jell14:11:45

ok yeah if you don’t mind I might give it a try

dnolen14:11:54

just pointing out that we don’t spend much time on it since it’s all low hanging fruit

jell14:11:59

of course

dnolen14:11:01

and people aren’t complaining about this kind of perf stuff

jell14:11:13

thanks again!

ericnormand15:11:45

@thheller the person who is asking me has all of their js "modules" in separate github repos. they were thinking about rewriting them in ClojureScript one at a time. but if each had an overhead of 95k, it would not be a win

ericnormand15:11:00

but it seems like they're going to have to require all of those repos into one project and do module splitting through closure

pesterhazy15:11:27

OMG, cljsjs is great

pesterhazy15:11:50

thanks to everyone who's contributed!! 🍺 🍺

dnolen15:11:37

@ericnormand if you mean they want to write their JS modules in ClojureScript but ship the JS - not a good idea

dnolen15:11:18

Google Closure is oriented around whole program optimization - so the tradeoffs start right there

mhuebert15:11:51

@thheller @dnolen thanks for the info. I’m packaging analysis caches for self-hosted cljs, and dissocing the superfluous :meta key from each def shaves 20-30% off the (zipped) file sizes. I’m not sure if it’s better to dissoc :meta, or dissoc all the keys direct from the def - the only place I know I’ll be using this stuff is for an implementation of doc

dnolen15:11:40

@mhuebert you can submit a patch, remove the duping and only combine in the :var-special emission

ericnormand15:11:04

@dnolen: yeah, that's what I'm trying to convince them of

dnolen15:11:00

@ericnormand right sounds like they think ClojureScript is like CoffeeScript - sugar to generate JS

dnolen15:11:24

anyways can’t do anything for people that looking for that kind of thing

dnolen15:11:24

@mhuebert it’s actually pretty desirable since that probably means it’s also 20%-30% faster to read the caches back

ericnormand15:11:51

@dnolen: they are publishing each module to npm separately, so I don't think it will work without a major change

dnolen15:11:28

@ericnormand yeah not interested in this “goal"

mhuebert16:11:49

@dnolen ok, i’m taking a look at it. some of the values differ between the :meta map and the def (for the keys #{:column :arglists :line :end-line :end-column :file}, example printout http://pastebin.com/hc7C7Rqa) and I haven’t tracked down exactly where all of those changes come from yet.

mfikes17:11:54

@jell FWIW, I took a look at the code path involved when you add the val argument. You can see that without it, it follows a more generic code path that essentially calls nth on the result of range, while with it, it follows a code path that “knows” about range and avoids ever calling nth and simply increments numbers.

royalaid17:11:05

Hey guys quick question about namespaces in a cider CLJS REPL. It seems that whenever I try to require a namespace that is in my project at the figwheel REPL, i.e. (require project.websocket) the REPL complains about that namespace not existing. However if I reference that namespace directly it seems to work just fine i.e. (project.websocket/test-fn). I am guessing this has to do with the closure compile step or figwheel reloading the page on save but I am kind of lost on how to proceed. Any hints, help, or ideas as to why this is the case and a way to reload my namespaces in the REPL would be much appreciated.

mfikes17:11:46

@royalaid Are you using a quote, as in (require ‘project.websocket)?

mfikes17:11:45

@royalaid After getting the exception from require it might be possible to do pst to learn more about where it is coming from. (I don’t recognize that one.)

royalaid17:11:04

That is the fullstack trace

royalaid17:11:10

didn't really help me much

juhoteperi18:11:24

@bbloom Btw. There exists a simple Socket REPL client for Vim: https://github.com/jebberjeb/clojure-socketrepl.nvim

juhoteperi18:11:45

Quite simple compared to Fireplace, there is no eval->response, only buffer of output

jell18:11:17

@mfikes thanks looking up the reduce implementation! I did gather that much on reading the code although I did not lookup the nth implementation (sorry about that, got too much excited with my findings). I personally think that (reduce + 0 (range 1e7)) looks more impressive than (apply + (range 1e7)), and I thought if (reduce + (range 1e7)) was running as fast it would have been even more epic 😛 (looks so much higher level than apply, even though it’s the same thing under the hood in that case). I now know it is indeed possible, but not the case just incidentally because that path was not optimised. Anyway, thanks for your time and the cool stuff you do! 🙂

domkm18:11:56

Has anyone used NPM packages (like react or exponent) via CLJS? Apparently, Google Closure now supports CommonJS/ES6 modules (https://github.com/google/closure-compiler/wiki/JS-Modules) but I haven't seen it used via CLJS yet.

dnolen18:11:52

@domkm supporting CommonJS/ES6 isn’t actually good enough, you need to support Node.js module resolution - that’s a pending PR on Google Closure though so ClojureScript will likely have that soon enough

domkm19:11:30

@dnolen I see, thanks for clarifying.

dnolen19:11:37

@royalaid it can’t find that namespace - it probably means you haven’t placed the source file in the correct place

domkm19:11:49

It looks like this (https://github.com/google/closure-compiler/pull/2130) may be the PR, for anyone interested.

thheller19:11:10

@domkm I wouldn't hold my breath on that getting usable anytime soon

thheller19:11:32

React for example does so many non-standard things

thheller19:11:47

and really doesn't follow node resolution at all

juhoteperi19:11:54

@domkm React and its dependencies do LOTS OF strange things like dynamically creating module.exports which Closure doesn't currently support

juhoteperi19:11:18

So even if Closure supports basic npm modules, supporting React is much more complicated

juhoteperi19:11:05

Oh well, seems like I'm just repeating what @thheller already said 😄

bja19:11:23

seems as though node doesn't have the optimization that makes (apply + (range 1e7))) fast

bja19:11:48

although, it's kinda interesting that clojure and cljs (on nashorn) are comparable in speed

bja19:11:34

is there a way I'm supposed to be able to drop directly into a nashorn-hosted cljs repl? This was the shortest invocation I could figure out java -jar cljs.jar -e "(require 'cljs.repl.nashorn) (cljs.repl.nashorn/-main)"

juhoteperi19:11:56

@domkm @thheller Here is my test with trying to use module processing with React: https://github.com/Deraen/circle-color/tree/object-assign

dnolen19:11:37

@bja not much shorter, but java -cp cljs.jar clojure.main -m cljs.repl.nashorn

bja19:11:34

@dnolen worth adding as an alias I suppose. thanks! (I mean a personal alias for me in my ~/.bashrc)

wildermuthn20:11:46

I’d like to check which protocols functions (methods?) are implemented by an object. satisfies? only checks that an object implements at least one method. Is there a simple way to check for a particular function having been implemented?

dnolen20:11:21

@wildermuthn satisfies? doesn’t actually check anything other than that you said you satisfied the protocol

dnolen20:11:47

and no there is no simple way to test that a specific protocol method has been implemented

wildermuthn20:11:23

Ok thanks. Is it a bad practice to only implement part of a protocol?

wildermuthn20:11:51

(I’m adding a method to a protocol is the issue)

dnolen20:11:06

if by “bad practice” you mean will someone get angry if you’re thing doesn’t work

dnolen20:11:12

probably … yes

dnolen20:11:10

I would think really long and hard about changing a protocol if people already depend on it

dnolen20:11:25

it’s too damaging of a change - just make a new protocol

dnolen20:11:38

this is the reason we put fns in front of important protocols

dnolen20:11:42

to protect users downstream

wildermuthn20:11:10

Ahhhh, ok. I should have just made another protocol. I began writing this before realizing what satisfies? does:

wildermuthn20:11:40

(this was just the start here… not necessarily well though out)

dnolen20:11:11

right so that looks fine to me

dnolen20:11:19

your public api is not a protocol, but a fn

wildermuthn20:11:41

so I’m making a library as I use the library, dog-fooding it. And I’m adding a protocol method I didn’t realize I needed.

wildermuthn20:11:15

I’ve done this a few times now. And end up just adding stubbed functions to a lot of types. But it seems, if some types don’t need those methods, perhaps those methods need to be a different protocol entirely?

wildermuthn20:11:29

(i.e., the event listeners)

wildermuthn20:11:48

K, thx, very helpful

anmonteiro21:11:57

@bja: I verified the same thing. (time (apply + (range 1e7))) in Lumo takes more than 1 second. It seems to take much less in Chrome (which also runs V8). I still haven't figured out yet, though Lumo is faster than Planck for other stuff. Most probably related to different optimizations by different JS engines

bja21:11:10

Lumo is infinitely faster when you're on Linux

bja21:11:30

although I guess JavascriptCore runs on Linux, and maybe Planck could too

darwin21:11:56

so, it runs 0 seconds under linux? 😉

mfikes21:11:00

@bja The Planck 2.0.0 betas do run on Linux

bja21:11:42

@mfikes ooh, will try that out

anmonteiro21:11:19

@bja: can you share some specific numbers?

anmonteiro21:11:31

Also what machine you're on

anmonteiro21:11:38

I'd be very interested

anmonteiro21:11:52

One thing that Lumo does over plain Node.js is the startup snapshot

anmonteiro21:11:23

So every CLJS function is already compiled (though lazily) when you start up the REPL

anmonteiro21:11:34

probably why you're seeing perf increase

bja21:11:31

do you have any recommendations for something like criterium for cljs/lumo?

bbloom23:11:31

so for folks doing client apps with optimistic updates, what’s everybody been doing for client vs server ids? i’ve just been handling it pretty ad-hoc. was wondering if people had solutions they like