Fork me on GitHub
#clojurescript
<
2017-02-08
>
darwin00:02:43

goog/DEBUG always worked, as far as I remember

Oliver George00:02:40

There was a fairly short post about effectively using goog.DEBUG somewhere. Wish I could find it now. Perhaps something for the clojurescript website.

sineer01:02:58

es6+jsx+flow syntax is insane! It makes me appreciate clojure simple syntax so much!!

pbaille08:02:48

Hi, is there a way to DRY this up?

(ns myns 
  (:require [foo.bar.baz.one :as one]
                 [foo.bar.baz.two :as two]
                 [foo.bar.baz.three :as three]))

Aron08:02:32

dry is overrated πŸ˜„

pesterhazy08:02:21

@pbaille there is but I wouldn't recommend it

pesterhazy09:02:28

my main reason is that you want to be able to grep for foo.bar.baz.one and find all places where you use the ns

pbaille09:02:44

okok I see

Aron09:02:05

πŸ˜„

pbaille09:02:17

and you cannot alias with

(:require
 (com.example client server routes))

pbaille09:02:25

or maybe you can?

rauh09:02:35

You can nest arbtirarily: (require '[a.b [c :as d] [e :as f]])

thheller09:02:52

@rauh @pbaille CLJS does not support prefix lists, so no you cannot do that

pesterhazy09:02:30

oh I didn't know that @thheller

pbaille09:02:33

ok I will not do that

pbaille09:02:44

but looks good to me

Aron09:02:33

action movies look good to me too

Aron09:02:42

and large explosions

pbaille10:02:32

@ashnur I don't know what makes you compare this (fancy) syntax to an action movie, but I think despite the fact that it is arguably complex, I find it quite clear. Easier that the destructuring syntax for instance.

Aron10:02:15

@pbaille my point is that i know lots of things that look good but i wouldn't do them myself

Aron10:02:38

"looks good" is not an argument in favor of one particular way of writing code over the other

Aron10:02:00

unless it's some competition in which code aesthetics play a role

Aron10:02:11

now, you said that you "find it clear" which is a very different notion, and i would say that it depends on your education and what you are used to, and it's not some inherent property of that particular way of writing code

Aron10:02:03

i have a colleague who is often arguing that he finds i++ way simpler to understand than i+=1 because in the latter there are 3 things to understand, which variable, what's happening to it and what is the value passed, while in the first case there are only two things to notice, which variable and what's happening to it. I can't agree with him, I think all this is just about what someone is accustomed to.

Aron10:02:37

how to have a default value for (aget somejsobj "someprop") ? πŸ™‚

grav10:02:12

Hey! We’re using transit/writer to encode certain javascript types (js/BigNumber) as "arbitrary precision decimal” (the β€˜f’ tag). Can we do the same with EDN using BigDecimals? Eg {:val (js/BigNumber. 3.1)} -> {:val 3.1M}

rauh10:02:34

@ashnur You should use goog.object.get. And if you need lazyness: or

thheller10:02:21

@grav not if you want 3.1M, you can however print BigDecimal using a custom tag and read that as such #my/bigdec "3.1" or so

thheller10:02:06

but there is no way to override the handler for M

grav10:02:48

Okay, no problem with M, but how do I use custom tags?

thheller10:02:16

write or read?

thheller10:02:56

cljs.reader or which reader are you using for edn?

thheller10:02:02

(reader/register-tag-parser! "my/bigdec" read-bigdec)

grav10:02:16

Write - but reading eventually

thheller10:02:35

in CLJS the print would go IPrintWithWriter protocol, just extend-type that onto BigNumber

thheller10:02:59

in CLJ you'd have to defmethod print-method BigDecimal to override the default

thheller10:02:37

that is a bit icky though if anything else ever prints and expects an 3.1M

thheller10:02:02

curious: why not stick to transit? it is better suited for this

grav10:02:12

Readability in development

grav10:02:07

But we might stick with it, if it’s too hacky. Though custom tags sounds like a good solution

grav10:02:24

Thanks for the assistance πŸ™‚

Aron10:02:47

people say that jvm is fast and everything, but the whole stuff is still too heavy and sluggish. i never know if i am waiting for my browser to run my code or me and my browser both waiting for the jvm to compile it

Aron10:02:17

i end up wasting lots of time refreshing and resaving just because nothing happens for way too long and i am unsure if it will

Aron10:02:42

i am using lein-figwheel currently

robert-stuttaford10:02:54

it should be live-reloading your code for you

Aron10:02:56

not to mention the 2 minutes while the whole thing wakes up from zero at the beginning

Aron10:02:25

although that happens only several times a day, but still boring to wait it out

robert-stuttaford10:02:39

have you watched bruce’s talks? does what you’re seeing match his demo?

Aron10:02:40

it does live-reload. i didn't say it doesn't, i said it's sluggish πŸ™‚

robert-stuttaford10:02:17

you shouldn’t need to refresh, then, which is what you said you were doing.

Aron10:02:59

i have to refresh because my code runs at browser load event

robert-stuttaford10:02:16

so maybe don’t have it do that until you’re happy it works?

robert-stuttaford10:02:22

sounds like this is a complaint that β€˜everything is slow’, which the only real answer is β€˜sorry to hear that’. specific issues can receive better assistance πŸ™‚

Aron10:02:44

i am sure i could rewrite to not have to do that, but i have not yet thought about how. that said, it shouldn't be slow at load, that's not a defense for slowness, that i shouldn't do it πŸ™‚

Aron10:02:04

not everything is slow

robert-stuttaford10:02:35

there’s what is, and there’s what we think should be. i find dealing with what β€˜is’ leads to happier results sooner

Aron10:02:13

that's actually something i can agree with, although I admit, i am an idealist. i don't like the real world stopping me doing what i like πŸ˜›

robert-stuttaford10:02:24

it could be that you’re reloading too much code because of how your namespace dependencies are set up. browser reloads involve a lot of network, which is always going to cost time

robert-stuttaford10:02:31

you and me both, buddy

Aron10:02:36

Aaaaanyway, if anyone has time to look at it and give me feedback what i should fix https://github.com/ashnur/cljs-combo-network

metametadata10:02:40

@ashnur I also struggled with figwheel reload times, these options helped in my situation:

:cljsbuild {:builds [{:id "dev"
                                         :compiler {
                                              :recompile-dependents false ; this makes hot reloads noticably faster. but in very rare cases can cause stale code bugs?
                                              :parallel-build       true ; mostly speeds up initial compilation
....

robert-stuttaford10:02:01

so i suggest you untangle your code from onload and set it up to run via figwheel’s reload fn instead

robert-stuttaford10:02:39

and follow bruce’s great advice for reloadable apps (so keeping state stable during reloads)

robert-stuttaford10:02:53

if you separate concerns like this, you almost always write simpler, faster code

robert-stuttaford10:02:13

this is generic advice though, and may not help you at all pinch-of-salt.gif

Aron10:02:17

you are talking about stuff i know nothing about, can i ask you to please don't just say names but give links or keywords that are easy to google?

robert-stuttaford10:02:56

i hope this helps you ashnur πŸ™‚ i understand this kind of frustration and actively work to eliminate it from my own life

robert-stuttaford10:02:32

almost always a common problem with a well understood fix

Aron10:02:12

yeah, that thing about frustration, i hoped that clojure will be different and it's actually worse

Aron10:02:21

whatever, not gonna start the rant again πŸ˜„

robert-stuttaford10:02:22

ah, so you’re new to clj/s?

pesterhazy10:02:38

also remember that a reloading workflow, when set up, gives you a lot of leverage

robert-stuttaford10:02:57

then watching a couple talks and actively applying what you see will give you a tremendous boost πŸ™‚

Aron11:02:22

robert-stuttaford: i don't think there is any cljs talk that could help me and i have not yet seen it. same goes for the one you linked. I will re-watch it of course because just because I saw it already doesn't mean I remember anything, but I definitely saw most of the relevant talks

Aron11:02:50

i follow the scene mostly because i realized very early that this is where the ideas are seeping into the mainstream frontend development

Aron11:02:24

but i would like to be able to force someone who is saying fast to sit down at my machine and make it "fast" in like 10 minutes and then i hook up my js environment and show what is the difference. jvm enthusiasts are blind to the reality imho :))

Aron11:02:06

i wait the day when cljs + figwheel or similar can be used without the jvm πŸ™‚

Aron11:02:17

and thanks again for your help, much appreciated!

Aron10:02:00

well, what do you consider new? i used mori/datascript for more than a year now actively in javascript projects, and most of the core ideas are not new

rauh10:02:19

@ashnur CLJS recompilation is pretty much instant, for me ~500ms when compiling a few files. And the browser loads them in another 200ms or less. So very very quick. Are you sure you aren't doing expensive computation when your browser exectues/loads the JS files?

pesterhazy10:02:19

because suddenly something that would take you a minute to verify now only take you 5 seconds

Aron10:02:26

the tooling though... well i am new to that because i never liked java/jvm and i never will πŸ˜„

robert-stuttaford10:02:31

the Dream exists. many of us live it. you just have to soldier through the bootstrap phase

Aron10:02:02

i think most people who say that just figured that easier to not have to do the things that make you deal with the hard stuff

Aron10:02:07

but that's not a path for me

pesterhazy10:02:07

so the upfront cost is (IMO) offset by the long-term payoff in confidence and velocity

rauh10:02:34

Not sure how expensive this one is: (def G (ggen/erdos-renyi 20 0.10)) but maybe defonce it if you can.

Aron10:02:52

i should've thought of that

Aron10:02:51

when this is done, i want a UI for selecting which random graph generator algorithm i want to use

Aron10:02:06

that should be in the reagent part

pbaille11:02:03

@ashnur "looks good" meant that I can't see any problems/downsides to this syntax, but I agree that I should be more explicit! the grep argument is not suffisant in my opinion. who is relying on grep to analyse a clojure project? (that's not rethorical) in clojure the code parsing should be always structural no? (not string based, but expression based). For me this syntax remove noise for not so much of a cognitive overhead. but as you mention it is a matter of education and taste.

pesterhazy11:02:30

the grep argument is a belief in the power of text (http://flylib.com/books/en/1.315.1.30/1/)

pesterhazy11:02:52

at least in the absence of better static analysis tools, grepping is very powerful

pesterhazy11:02:17

it also helps people new to the code find their way around

pesterhazy11:02:16

it's not a knock-down argument but I think it's a pretty good reason not to needlessly impair greppability

pbaille11:02:26

yes I agree that grep is a powerful tool but for clojure source parsing it does not make much sense I think. But I see your point and agree with it. Thank you for the link I will read it.

Aron12:02:23

i am having trouble trying to imagine how would i setup :on-jsload

Aron12:02:04

it seems to me that i should not just wrap almost everything into that function, but that i should write a whole lot of other stuff that goes around and resets values in the DOM

Aron12:02:58

seems like a waste of time, considering that i can just hit CTRL+R now and the same thing happens by itself.

Aron12:02:30

i am really hoping here that someone will correct me on this πŸ˜‰

Aron12:02:24

if i just had a simple state -> view system as i like normally to have, then it would be enough to reset the state

Oliver George13:02:05

@ashnur As an example, I build on re-frame/reagent. I use :on-jsload to trigger a fresh render so that if view fns have updated the UI reflects them. Also, if I have "page transition" behaviour in my single-page webapp then I might retrigger that too... that's useful or not since it resets some app state. Depends on my need.

Aron13:02:09

that sounds as i imagined it. the thing i am building now is mostly just about what's on a <canvas>, and that part i render out with d3

Aron13:02:20

so this function that resets stuff should reset the d3 state

Oliver George13:02:02

Sounds like it might be useful then.

Oliver George13:02:28

Again, as an example, my page refresh is fairly heavy since there's 22k lines of code and a heap of features. Figwheel pushing updates is super fast by comparison. Caveat being that when I change a core lib which many files rely on the refresh slow as most files are reloaded.

Aron13:02:59

makes sense

Oliver George14:02:39

And while I'm singing Figwheel's praises there's also the wonder of keeping your app-state so that you can make incremental code changes to a specific feature. That can avoid the issue of having to click a bunch of buttons to recreate a specific scenario after refresh.

tomaas14:02:28

hi, why can't I do this: (map #([:div %]) some-collection)?

dnolen14:02:36

@tomaas it’s just not how the fn literal works

dnolen14:02:00

that becomes (fn [%] ([:div %]))

tomaas14:02:45

thanks, I see now

tstephens16:02:24

question about closure-compiler JS libs and exports: we have a clojurescript project which pulls in a closure-compiler compatible JS project via the :libs compiler flag. However, the @exports in the JS project don't get exported into the resulting minified JS. We're using another non-closure-compiler, third party JS which expects the symbols from the closure-compiler-compatible JS project to be available, but they aren't, because they're minified. Is there any way to fix this?

dnolen16:02:17

@tstephens do you mean @export?

tstephens16:02:35

sorry, just mis-placed the `

dnolen17:02:00

@tstephens it should work, if it doesn’t work you should be able to reproduce without ClojureScript

tstephens17:02:21

as in, create a JS project, pull in another one, and see if the inner projects @exported symbols are in the output?

tstephens17:02:11

i can try to give that a shot

tstephens18:02:47

@dnolen still working on reproducing it with a JS project, but the docs here (https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler#export-export-sometype) say that the closure compiler needs to be executed with β€”generate_exports to get the JSDoc @export annotations to be included, and I don’t see any way to enable that option via the clojurescript compiler?

dnolen18:02:52

@tstephens we might be missing it, file a JIRA ticket

dnolen18:02:08

@tstephens in the mean time you’ll have to work around it via goog.exportSymbol then

Aron19:02:15

i am really having an issue to write my code so figwheel would reset with :on-jsload

Aron19:02:56

if someone has a bit of time, i would really appreciate some input, i tried to work into the code what people already told me

tstephens20:02:18

@dnolen created ticket http://dev.clojure.org/jira/browse/CLJS-1931 for the β€”generate_exports issue. thanks for your help

dnolen20:02:32

@tstephens thanks for the report!

dnolen20:02:46

hopefully simple to fix will take a look Friday

tstephens20:02:58

awesome, thanks

Aron20:02:53

if no time for that, it would help to know how can i reduce the size of the question so people have time to look at it

geoffs20:02:59

@ashnur a really helpful way to reduce a problem/question is to create a minimum reproducible example. Especially when talking about project configuration, starting from a clean-slate and having the absolute fewest lines of code to demonstrate an issue makes it way more enticing to look at

Aron20:02:33

@geoffs i am aware of the minimal example way, that's why i am asking how to do it.

geoffs21:02:39

so I would expect a minimal example to be just setting up a basic figwheel config that has :on-jsload just log to the console

Aron21:02:21

how would that help me? i am fairly sure that would work πŸ™‚

Aron21:02:12

maybe i am not clear enough. my issue is not that on-jsload doesn't work. my issue is exactly that i don't know how to make it work for me in this situation where i am drawing to canvas with d3

Aron21:02:31

if i remove the complexity, i remove exactly the thing i want to connect to on-jsload

isak21:02:59

@ashnur one thing that may be problematic is you have this on the top level:

(def init-node (rand-int (aget (aget Gjs "nodes") "length")))

(def messages (js/Array))

(.push messages init-node) 
, and then you also have some mutations in the lifecycle methods. Probably better to just do that stuff in the lifecycle methods also. (Not sure if that is the problem, though)

Aron21:02:44

i am not sure what is a "lifecycle method"

isak21:02:59

:component-did-mount
(fn [ this ] ...) 

Aron21:02:15

oh, the reagent stuff, i see

thheller21:02:29

@ashnur it looks like you are trying to learn too many things at once: cljs itself, figwheel, reagent

Aron21:02:47

thheller do you think? πŸ™‚

jr21:02:03

@ashnur replace the body of on-js-reload with (reagent/force-update-all) and that will work

jr21:02:17

why reset state on code reload?

thheller21:02:22

maybe a simpler figwheel app without anything

thheller21:02:25

then add reagent, then your stuff

thheller21:02:52

to get a better feel for how things fit together

thheller21:02:22

it still looks like you are coding JS but in CLJS

thheller21:02:32

I did that for quite a while in the beginning too

Aron21:02:04

@thheller i think that you are mistakingly thinking that i use js methods because i don't know the cljs solutions

Aron21:02:13

but i only use those to work with d3

Aron21:02:32

i used mori a lot before, cljs datastructures are not alien to me

Aron21:02:22

similarly, reagent/react is very straightforward in itself as an idea, although I admit, learning a lot of new terminology is really hard, when people don't even know what i am asking about

thheller21:02:00

no what I mean is that you have a lot of functions

thheller21:02:04

taking no arguments

thheller21:02:10

and working with globals

Aron21:02:48

well, i mentioned before that after finishing i hope i will be able to find solutions that are more idiomatic to cljs

Aron21:02:06

however to keep the performance good, i think i need lots of "globals"

Aron21:02:19

@isak i think i understand now. took me a bit of time to pull the code and launch everything

thheller21:02:35

when it comes to live reloading, everything in your ns is executed

thheller21:02:52

that means that the (reagent/render ...) at the bottom is called

jr21:02:00

ashnur use reagent/force-reload-all

jr21:02:11

I can confirm that it fixes your issue

thheller21:02:23

which will insert a new canvas AFAICT

Aron21:02:39

@jr thanks, i will try, i am going in order πŸ™‚

Aron21:02:14

i am really curious btw if it's possible to not use "globals" and reach similar performance, because even in the js version i wished i could've done that but eventually had to give up and just use variables from shared scope

Aron21:02:21

@jr thanks, it really works, now i have to go and read about it to find out why it works πŸ˜„

thheller21:02:42

(defn ui-control
  [state]
  [:div {:class "Control__ui"}
  [:button {:on-click #(reset! state state)} "restart"]])

jr21:02:54

the globals you are defining in the namespace will be re-evaluated (unless marked defonce)

thheller21:02:56

that reset! cannot work, you cannot set state to state

Aron21:02:08

yeah, the button now throws an error

Aron21:02:38

the whole state thing is not used now. my original idea didn't work out and decided to just port everything first and then fix things one by one

jr21:02:52

the dom does not disappear when reloading js files

jr21:02:03

so you have to tell the react component (in the dom) to re-render given new code

Aron21:02:28

@jr yeah, so to fix this, i have to use those reagent lifecycle methods @isak mentioned, right?

jr21:02:11

no you call force-reload-all. the reagent components will only automatically re-render if one of their dependent reactive atoms has changed

Aron21:02:07

ok, so if i want to re-render on-jsload then i should change some atom in :on-jsload that is tied to reagent

Aron21:02:11

did i get that right?

jr21:02:53

no you don't want to do that

jr21:02:04

then every component will have to subscribe to that reactive atom

jr21:02:12

force-reload-all exists for this reason

Aron21:02:27

yeah, i was reading the docs for it right now

jr21:02:01

sorry I mean force-update-all and not force-reload-all

Aron21:02:41

heh, i didn't even realize πŸ˜„

Aron21:02:15

@thheller btw, i was never able to learn from easy examples. if I don't see how things work in the edge case scenarios, i simply confuse everything with everything. I knew that trying to do shared mutable state in cljs is not going to be easy, but that's exactly why i chose this as a learning project πŸ™‚. If I can do this, I am not going to be afraid of trying something that's less... ugly πŸ˜›

Aron21:02:39

and thanks everyone, now i know what i will do tomorrow at work πŸ˜„