Fork me on GitHub
#clojurescript
<
2018-02-24
>
tony.kay03:02:43

ok, so help me out here. I understand that #js is a reader tag, and that the conversion happens before macro expansion and compile. What, exactly, does this tag output?

tony.kay03:02:44

I ask, because I’m doing some benchmarking of alternatives, and for some reason I’m seeing clj->js run faster than #js, and I’m trying to figure out if I’m losing my mind 🙂

noisesmith03:02:43

it creates a string to insert into the source file

noisesmith03:02:08

clj->js should do its work at runtim, #js should 100% happen while compiling

tony.kay03:02:11

yeah, I’m looking at the generated js now

tony.kay03:02:21

that’s what I thought, and that’s what I see in code

tony.kay03:02:35

now that I’m looking…I must be measuring incorrectly.

noisesmith03:02:05

if you are measuring the runtime cost, what do you measure - load time for the text with the js data in it?

tony.kay03:02:00

I’m measuring something more complicated: the effects of using #js on props sent to react vs using clj->js

tony.kay03:02:17

so I’m measuring time to render a frame

noisesmith03:02:02

you know #js isn't a deep transform right?

tony.kay03:02:09

It’s gotta be an error. Yeah, I know.

tony.kay03:02:20

I’ve been working too many hours today…has to be a math error

tony.kay03:02:34

My earlier measurements showed it at 8% slower in the expected direction, so this new measurement just has to be broken somehow

tony.kay03:02:07

8% weighed against the overall task

tony.kay03:02:28

trying to quantify cost-benefit of using vs not

tony.kay03:02:06

part of the deal is chrome’s js optimization improves very slowly, so getting to a stable number is painful

mfikes03:02:38

@tony.kay It would be interesting if you found a case where clj->js on some Clojure values somehow ended up being faster than #js literals. Here are a couple relevant posts that might be useful http://blog.fikesfarm.com/posts/2017-11-09-avoid-converting-javascript-objects.html http://blog.fikesfarm.com/posts/2017-11-18-clojurescript-performance-measurement.html

tony.kay03:02:11

I’m looking into what’s going on via Chrome’s performance tab now

mfikes03:02:42

In terms of the underlying generated JavaScript, fire up Lumo or Planck with -v or enable :repl-verbose. (clj->js {:foo 1}) turns into cljs.core.clj__GT_js.call(null,new cljs.core.PersistentArrayMap(null, 1, [new cljs.core.Keyword(null,"foo","foo",(1268894036)),(1)], null)) (prior to Closure optimization) while #js {:foo 1} turns into ({"foo": (1)})

tony.kay04:02:00

Yeah, I’m looking at the source. I knew that’s what it did, but I’m clearly not measuring what I think I’m measuring. Probably some async thing going on I don’t realize that is throwing things off

tony.kay04:02:39

It seems pretty impossible to do extra work in between A -> B, end up with B, and have that be faster than just using B to start with

tony.kay04:02:15

but interpreters are screwy things, so it makes you doubt yourself

mfikes04:02:10

For me, in Lumo (which also uses V8) (simple-benchmark [] (clj->js {:foo 1}) 1e7) -> 45522 msecs (simple-benchmark [] #js {:foo 1} 1e7) -> 20 msecs

tony.kay04:02:37

no, it is an async thing…I’m measuring the time to submit the thing, not render it 😕

tony.kay04:02:10

so, I’m not going insane..just not doing what I thought

tony.kay04:02:36

yeah, fixed my measurement. It is much more in line with expectations now: 2ms w/clj-js vs. .8ms without.

raycar509:02:27

helloo, I'm having a problem with clojurescript and core.async, I keep getting the error "Invalid :refer, var cljs.core.async/!> does not exist"

raycar509:02:57

(ns testing (:require [reagent.core :as reagent :refer [atom]] [clojure.core.async :as async :refer [chan go <! !>]]))

raycar509:02:55

I do have the dependency declared in lein: [org.clojure/core.async "0.3.465"]

raycar509:02:27

any Ideas about what I'm doing wrong?

juhoteperi09:02:54

@raycar5 which Cljs version are you using?

juhoteperi09:02:09

oh, wrong async namespace, the correct one is cljs.core.async

raycar509:02:33

tried changing both the require and the dependency to cljs, still error 😕

juhoteperi09:02:14

okay, next guess, the name of the fn is wrong: http://clojuredocs.org/clojure.core.async/%3E!

raycar509:02:24

@juhoteperi you are right, i wrote !> instead of >!

raycar509:02:35

what a stupid mistake 😅

Aron11:02:53

if I have two sets that I know that are disjoint, how can i use the data as a single set? so i don't have to union or map over a list of sets every time

mfikes14:02:10

@ashnur If you want to test for membership, some-fn could be used to form a new function that looks at each set for you.

(let [s1 #{:a}
       s2 #{:b :c}       
       f (some-fn s1 s2)]
  (f :c))
What operation(s) do you want to support on the two disjoint sets?

Aron16:02:29

@mfikes i think what i want is impossible. i was wondering if i could literally reuse the memory space of 2 sets as a single set.

noisesmith16:02:22

yeah, sets are not simple enough for that to be simple - but if you take a union, you will share memory between the added data and the original sets in most cases

Aron17:02:50

well, i hope so

roti18:02:15

has somebody worked with promises in clojurescript? either javascript promises, or implemented directly in clojurescript ?

justinlee18:02:41

plenty of people have

noisesmith18:02:48

@roti note that clojure has a "promise" which is just a container that can be given a value exactly once and doesn't have one by default - if clojurescript core ever got a promise it would likely be the same thing (and not at all what you are talking about)

roti18:02:43

hmm, I just found promise-chan, though I don't understand the doc completely ("Once full, puts complete but val is dropped (no transfer).")

noisesmith18:02:39

@roti it's just like a clojure promise: it accepts exactly one value one time, after that every put is ignored, and every take returns the first value

noisesmith18:02:48

it has nothing to do with js promise

noisesmith18:02:23

I'll attempt another description - in clojure a promise is something that starts with no value in it, then gets a single value, and after that always has that value. It has no callbacks, triggers, watchers, failure states, etc.

roti18:02:55

that's good enough actually, I wonder if one could have a similar error behaviour like Javascript promise chains

noisesmith19:02:07

which is all an aside if you want to use a promise from js via clojurescript - just making sure that distinction is understood

noisesmith19:02:38

@roti there no way to put an error in a clojure promise or promise-chan because they don't represent state or execution

noisesmith19:02:55

if your code (deliver p (/ 1 0)) errors, p doesn't get a value

noisesmith19:02:03

the error isn't tied to p in any way

noisesmith19:02:40

I mean you can use a data type that represents an error of course (deliver p (ex-info ...)) but I think you want something different

roti19:02:59

yes, I am looking to write asyncronous code in synchronous style 😛 , which also means that errors/exception should short circuit the execution steps and jump to the nearest error handler

roti19:02:35

like true exceptions, promise chains mimic that behaviour

noisesmith19:02:37

right, clojure promises are not the right thing for this, and I'm sorry I mentioned them - just wanted to make sure you didn't get side tracked

orestis19:02:58

@roti Checkout funcool/promesa

justinlee19:02:44

For the record I’ve found regular Js promises with the threading macro to be serviceable

roti19:02:12

@lee.justin.m you mean the ones returned by google closure? or es6 promises?

justinlee19:02:51

Es6 promises

justinlee19:02:17

I’m usually working with a library that returns one

noisesmith19:02:09

fun side note, TIL that clojure reverses the original definition of "promise" and "future" https://en.wikipedia.org/wiki/Futures_and_promises

noisesmith19:02:32

that article even mentions what core.async calls promise chans, but calls them futures - because clojure inverts the original naming

zentrope19:02:20

Does Clojure inherit its concept of future from Java?

noisesmith19:02:51

@zentrope yes the function future directly creates a java Future and that's probably why the names are flipped

leontalbot19:02:58

Hello cljs! I’d like to have a single-click and a double-click event handler where the single-click one will be fired only is no double-click event is fired. Would you know any snippet I code study?

leontalbot19:02:44

@lee.justin.m Thanks! What do you think of that:

justinlee21:02:19

Not sure! Haven’t seen that

mfikes20:02:26

@ashnur In ClojureScript nearly everything about collections and how they are used is done indirectly via protocols, so you could in theory make a new (defrecord double-set [a b]) and then go through the trouble of implementing all of the protocols needed like ICollection so conj works, ISet so disj works (each presumably heavily reusing the memory of the passed sets making a new double-set as needed). I wonder, though, if doing this would actually result in lower memory consumption than a new set produced via clojure.set/union.

mfikes20:02:47

I guess if you really wanted to, you could track elments added and removed via two more smaller sets, and then make all of the other operations also consult those side sets.