Fork me on GitHub
#clojurescript
<
2016-10-18
>
Pablo Fernandez08:10:26

In my project.clj I have two builds, one for prod and one for dev. Is there a way for the app to know which one is running without adding extra source files that I include in one or the other?

anmonteiro08:10:17

@kenny: there's just no way around it in ClojureScript. If that namespace requires DataScript, user projects that require it will need a dependency on DataScript

anmonteiro08:10:30

See e.g. the cljs.spec.test namespace. If you require it you'll need to have test.check in your dependencies

anmonteiro08:10:26

@pupeno: in your production build you could add :closure-defines {goog.DEBUG false}

anmonteiro08:10:34

The you only need to check whether goog.DEBUG is true or false and you know which environment the app is in

Pablo Fernandez08:10:51

I see… that might work 🙂

anmonteiro08:10:19

@pupeno: reference for the closure-defines compiler option: https://clojurescript.org/reference/compiler-options

lxsameer08:10:17

what do you guys uses for i18n and l10n

dm308:10:08

@lxsameer - ptaoussanis released https://github.com/ptaoussanis/tempura yesterday - I'd check that out

lxsameer08:10:25

but it does not have l10n support

dm308:10:15

sorry, can't help on that front

dm308:10:54

is there a way to get the locals in a clojurescript targeted macro?

dm308:10:00

e.g. in Clojure - clojure.lang.Compiler/LOCAL_ENV

herbm08:10:07

@0farcher lxsameer, Untangled has (a sort of strange) i18n support -- trying to learn untangled now, presuming it works as billed, it also seems rather convenient -- just write in English (or whatever) and there's an extraction for all the strings which you have translated and then placed put back in the project

herbm08:10:23

@lxsameer -- yw, suppose to be your tag but the 'helper/picker' didn't help me 🙂

anmonteiro08:10:35

@dm3 perhaps (:locals &env)?

thheller08:10:22

@lxsameer I would recommend to look at what closure providers in terms of i18n/l10n and build on top of that as it will have compiler support

thheller08:10:33

should only need a very thin cljs wrapper

dm309:10:21

@anmonteiro thx, I'll try working with that.

nikki09:10:36

is it weird to use clojure-for-the-brave-and-true in a clojurescript env

lxsameer10:10:30

should i do anything special for cljc to use in clojurescript ?

lxsameer10:10:07

@madstap yeah i already saw that buddy, thanks

darwin11:10:14

@pupeno I needed similar check, but for my macros, to decide which variant of code to generate, I tap into clojurescript compiler internal state, if I need it in cljs, I emit the value to clojurescript to be visible during runtime: https://github.com/binaryage/cljs-oops/blob/eefe95045ac307284290f04514066f8cb4d1917a/src/lib/oops/config.clj#L21 disclaimer: this is might break in the future of course, so having tests covering this is a must

lvh14:10:50

Are there any helpful tools for finding the problem when getting StackOverflowErrors when compiling CLJS files?

lvh14:10:59

I dunno if that’s e.g. a circular dep or whatever

dnolen14:10:35

@lvh the stack trace is usually quite helpful in these situations

dnolen14:10:58

we have code to detect circular deps, though you may have found a case where it doesn’t work

lvh14:10:27

gotcha; thanks

lvh14:10:37

It’s complaining about a ns I didn’t even touch, though, which is weird

dnolen14:10:17

@lvh the stack trace is nearly always pointing at the real problem - even if it seems strange on the surface

lvh14:10:45

okiedokie; then it’s blowing up because of core.async — I’l ltry excising it

lvh14:10:14

yeah; now it’s complaining about sente 🙂

dnolen14:10:27

unlikely that core.async is the issue

lvh14:10:02

- clojure.lang.ExceptionInfo: failed compiling file:/Users/lvh/Projects/rackspace/shrieker/src/shrieker/billing.cljs {:file #object[java.io.File 0x2b67d8ad "/Users/lvh/Projects/rackspace/shrieker/src/shrieker/billing.cljs”]} - Caused by: clojure.lang.ExceptionInfo: at line 1 jar:file:/Users/lvh/.m2/repository/com/taoensso/sente/1.8.1/sente-1.8.1.jar!/taoensso/sente.cljs {:file #object[java.net.URL 0x5e23795f "jar:file:/Users/lvh/.m2/repository/com/taoensso/sente/1.8.1/sente-1.8.1.jar!/taoensso/sente.cljs"], :line 1, :column 1, :tag :cljs/analysis-error}

lvh14:10:34

hm; maybe I should try with a much larger stack size

lvh14:10:53

Now I’m down to "Caused by: java.io.FileNotFoundException: /Users/lvh/Projects/rackspace/shrieker/src/shrieker/events.cljs (Too many open files in system)"

lvh14:10:21

I’m not sure why that’s the case, this app really isn’t that big

lvh14:10:30

(I did add another file though; I guess maybe that was one too many)

dnolen14:10:20

@lvh it’s possible there’s a file leak somewhere, though would be surprised no one has run into that before

dnolen14:10:26

but I wouldn’t rule that out

dnolen14:10:31

@lvh ok there is a file leak

lvh14:10:57

Any idea what I might be doing to cause it, and if there’s a workaround?

lvh14:10:40

It did happen when adding a new NS

dnolen14:10:55

@lvh hrm there’s no good workaround actually - I’ll probably cut a release just to address this issue

dnolen14:10:30

@lvh it would be helpful if you could test master when I fix it to demonstrate that this fixes the issue for you

lvh14:10:33

awesome, thanks 🙂

robert-stuttaford14:10:54

i humbly request that you also include http://dev.clojure.org/jira/browse/CLJS-1821, @dnolen, please 🙂

lvh14:10:07

I’m not sure if I can, we’re stuck on like 1.7 for bad reasons, and I think we haven’t figured out how to upgrade to current versions of cljsbuild/figwheel without gratuitously breaking everything

lvh14:10:14

But I’ll try.

robert-stuttaford14:10:43

thank you! much appreciated!

lvh14:10:33

@dnolen That seems like it wouldn’t affect the need for a bigger stack size, though

lvh14:10:57

(that changing something leads me to believe that that’s just the recursive descent parser having a really good time, not a broken circular dependency check or something)

dnolen15:10:10

@lvh concluding anything at this point is unwise, since your problem isn’t a minimal one

dnolen15:10:22

I have no idea what you tooling is doing, and I don’t want to know 🙂

dnolen15:10:49

@lvh if you can replicate the issue with just ClojureScript (after the other fix) then we can take a look

lvh15:10:09

Yeah; I’m trying to replicate it reliably locally first

adammiller16:10:45

Can anyone point me in the right direction for overloading a function on a js object from clojurescript? Specific example... I’m using google closure autocomplete and I need to overload selectRow on the InputHandler.

dnolen16:10:04

@lvh please try a build from master, thanks

dnolen16:10:38

@adammiller Google Closure should have examples of subclassing their components

lvh16:10:04

dnolen BTW; I did eventually discover a bug: it was a circular reference problem, and I’m guessing it didn’t get caught because the reference was using varquotes

lvh16:10:34

I’ll still try the master build though

dnolen16:10:39

@lvh “varquotes” ?

lvh16:10:52

I thought that was called a var quote

dnolen16:10:06

@lvh that still isn’t telling me anything

dnolen16:10:08

zero context here

dnolen16:10:21

what do vars have to do with circular references at all?

lvh16:10:45

They’re orthogonal; but you suggested that the circular reference detection might have bugs in it; I think one of them might be related to referring to something via a var quote, rather than referring to it directly, because that’s the most obviously unusual part about this code

lvh16:10:12

So, when I run it against master, I’m expecting the stack overflow again, but maybe not running out of fds

dnolen16:10:16

@lvh the circular dependency stuff is only about ns forms

dnolen16:10:30

I don’t see how vars could play into this at all

lvh16:10:40

OK, I guess not then.

dnolen16:10:41

but I would need to see the stack trace

jrheard16:10:20

@viebel last night i used klipse to help me understand the difference between the js generated by (for) and the js generated by loop/recur on a (make-array) - very helpful, thanks! 🙂

Yehonathan Sharvit16:10:22

@jrheard happy that you found it useful. Can you share the url of your code in the #klipse channel?

lvh17:10:08

@dnolen: master looks like it fixed the issue; thanks!

dnolen17:10:57

@lvh and the circular thing you were talking about?

lvh17:10:06

@dnolen: Already worked around it, but currently persists. I'll try to get a minimal case. Currently on phone though, so no promises on ETA :)

lvh17:10:16

@dnolen: just so I understand correctly: circular dependency detection means I should not see a stack overflow that goes away when I remove the circular dependency, right?

dnolen17:10:38

you misunderstood what I was saying before

dnolen17:10:43

I have no idea what your issue is and no information

dnolen17:10:33

setting your issue aside since I do not understand it

dnolen17:10:51

ClojureScript disallows circular dependencies between namespaces, that’s it

lvh17:10:27

Yep, that's what I understood . But does "disallow" mean "undefined behavior", "error message that details the dependency cycle " or something else entirely? Even if I can reproduce minimally, I'm trying to figure out if it would even be a bug.

dnolen17:10:13

@lvh we throw an exception on circular deps between namespaces

lvh17:10:55

Super; thanks :)

jrheard18:10:07

having trouble figuring out how to access the js = and == functions in clojurescript - any tips?

jrheard18:10:31

i could have sworn i once saw a way that you can embed a string of raw javascript in your cljs and run it, but am having trouble finding it in google

dnolen18:10:28

@jrheard you really should not do that unless you’re ok with your code suddenly not working one day

jrheard18:10:39

yeah, i don’t want to do the raw embed string thing

anmonteiro18:10:44

@jrheard js* is supposed to be for internal stuff only. you shouldn’t have the need to use it.

jrheard18:10:45

i just want to use the js equality operator instead of cljs eq

dnolen18:10:08

@jrheard assignment = is just set! with exception that it won’t work on locals

jrheard18:10:21

heh i was confused, been in cljs too long

jrheard18:10:25

i didn’t mean = at all, just == and ===

jrheard18:10:27

my mistake

jrheard18:10:35

good to know though 🙂

jrheard18:10:20

(i’m in a tight loop and just want to see if eg true === true)

dnolen18:10:25

@jrheard identical? is ===

dnolen18:10:35

if you must, coercive-= is ==

jrheard18:10:45

awesome, good to know - i promise i won’t use it 🙂

jrheard18:10:56

identical? is exactly what i was looking for

jrheard19:10:04

big fan of chrome devtools’ profiling support, plus source maps

jrheard19:10:13

performance investigations are a (relative) breeze 🙂

dnolen19:10:29

glad to hear it 🙂

jrheard19:10:26

is there good documentation somewhere on the correct way to use into to get performance? i’ve got a 2d javascript array of booleans that i’m trying to turn into a 2d cljs vector of keywords, and currently i’m doing this:

(into []
        (for [row an-array]
          (into []
                (for [full? row]
                  (if full? :full :empty)))))
but profiling indicates that i’m spending all of my time in this function, so i must be doing something wrong here

jrheard19:10:14

i could manually make and fill transients, but into seems like it wants to do that for me, so i’m betting that i shouldn’t be using for here but should instead be using.. something else?

jrheard19:10:10

profile UI if it’s helpful - https://www.evernote.com/shard/s11/sh/78e6bc21-1c88-4629-a654-fb23c04f8a32/2a62f1f0edbae168 - seems like i’m spending all of my time in these fors; again, i’m pretty sure i’d be easily able to make+fill+persist transients by hand, but i feel like i’ve read that there’s a more graceful way of accomplishing that

dnolen19:10:52

@jrheard using a lazy seq w/ into isn’t going to be fast

jrheard19:10:16

is reduce the right tool to reach for?

dnolen19:10:42

gimme a second

dnolen19:10:39

(into [] (map (fn [x] (if (true? x) :full :empty))) #js [true false true])

dnolen19:10:49

into calls transduce

dnolen19:10:55

transduce calls reduce

dnolen19:10:02

reduce will use array-reduce

jrheard19:10:07

ah, i think i follow

dnolen19:10:37

the above will simple end up in low level loop on the array

dnolen19:10:27

so it should be pretty zippy if :static-fns true (implicit if you’re doing an :advanced build)

jrheard19:10:47

awesome - i’ll read transduce and array-reduce, and will learn what :static-fns does 🙂

dnolen19:10:20

@jrheard actually you should just try the into I wrote above

dnolen19:10:36

the standard library is pre-compiled with :static-fns true

jrheard19:10:50

gotcha, will do

jrheard19:10:17

trying

(into []
        (map (fn [row]
               (into []
                     (map (fn [cell]
                            (if (true? cell) :full :empty)))
                     row)))
        an-array)
, and i see a noticeable (~2x) speedup! looks like this is exactly the use-into-to-get-performance-without-making-your-own-transients-by-hand usage i was looking for, thanks 🙂

Alex Miller (Clojure team)19:10:15

you can go one step further and use a transducer inside the into call too

jrheard19:10:33

hm, i thought that by doing (into [] (map foo bar) an-array) i was using a transducer in the into call - is that not what you mean?

jrheard19:10:57

err, (map foo)

Alex Miller (Clojure team)19:10:12

oh, maybe you are :) just hard to read all the indents properly

jrheard19:10:28

heh, yeah, i had the same issue when reading david’s example 😄

dnolen19:10:18

@jrheard there’s probably an optimization opportunity here that I hadn’t considered ...

dnolen19:10:46

one problem is that fns which are not multi-arity do not produce fast paths

dnolen19:10:21

but typically what you pass to map is not multi-arity, just an anonymous fn

dnolen19:10:33

so you’ll go down a slower path via JS primitive .call

dnolen19:10:59

so something to look at

dnolen19:10:40

there are some code gen challenges though so not as simple as it seems

arohner19:10:48

Is it specified what should happen you have foo.cljc, foo.cljs and (:require [foo])

danielcompton19:10:29

@arohner pretty sure the more specific one is chosen

danielcompton19:10:48

so if you're calling from CLJS then foo.cljs

anmonteiro19:10:33

@arohner @danielcompton is correct. In addition, :require-macros will load the .cljc

anmonteiro19:10:28

@arohner actually, if you’re on a ClojureScript version lower than 1.9.229, you might encounter weird behavior

jrheard19:10:16

@dnolen good to know - at this point the function i was optimizing is now plenty fast for my purposes, but i’ll keep that in mind if i run into a similar situation, thanks for the heads up

dnolen19:10:25

@jrheard also I forgot how this worked - it should definitely be faster with your production build when :static-fns true is applied globally

jrheard19:10:21

yeah, i think i’ve probably been worrying too much about optimizing various parts of my side project that are slow in dev - often when i do a production build, i find that they’re suddenly 10x faster 😅

anmonteiro19:10:45

@jrheard depending on the project, of course, but if you find that you don’t constantly redefine functions at the REPL (e.g. with different arities), it should be somewhat safe to also use :static-fns in dev mode

jrheard19:10:33

i’m using cursive + figwheel, would static-fns interfere with those?

jrheard20:10:00

these articles look extremely relevant, thanks 🙂

dnolen20:10:53

@jrheard yeah there are many optimizations that we apply only in productions builds, some of these have a huge impact

dnolen20:10:05

converting all keywords into constants is huge for example

jrheard20:10:14

ah, that makes sense

dnolen20:10:48

@jrheard also Closure eliminates closures (sounds funny doesn’t it?)

hlolli20:10:50

How can I make unicode characters become integers in cljs? I have this "\u22126" but (.fromCharCode js/String (goog.string/parseInt "\u22126")) wont do it.

dnolen20:10:42

@hlolli hrm, whatever people do in JS should work no?

hlolli20:10:38

ok, I somehow made wrong assumptions on this method,.. I check.

hlolli20:10:11

@dnolen all the unicodes return the number 92 😕

dnolen20:10:05

@hlolli what are you trying?

hlolli20:10:14

or 8722 (.codePointAt "\u22126" js/String 0)

dnolen20:10:30

that’s not right

dnolen20:10:46

it’s method on string instances

dnolen20:10:51

@hlolli the examples on the MDN page work for me

hlolli20:10:53

yes, I get often confused with interop as I never properly learned js 😞

dnolen20:10:21

(.codePointAt "\u22126" 0)

hlolli20:10:33

cljs.user> (.codePointAt "\u22126" 0)
=>8722
Whereas this number is suppose to be -6.

dnolen20:10:57

@hlolli I get -6 for index 1

dnolen20:10:19

oops I do not

dnolen20:10:25

also the behavior I see is identical to JS

dnolen20:10:33

8722 for 0, 54 for 1

dnolen20:10:12

the string prints as "−6"

dnolen20:10:20

but that dash is a unicode char

dnolen20:10:25

so all this seems right to me

dnolen20:10:30

and again - identical to JS behavior

hlolli20:10:28

You say you get 54 but prints as -6, just scratching my head...

hlolli20:10:26

ahh ok, I was missing that part that 54 is the charcode coming from unicode. Now I get positive 6, but that's fine, thanks @dnolen

dragoncube23:10:42

@dnolen “we apply only in productions builds” - is this for :advanced only or :simple applies too?

anmonteiro23:10:55

@dragoncube :static-fns needs to be explicitly set to true for simple compilation

anmonteiro23:10:29

same for :optimize-constants