Fork me on GitHub
#clojurescript
<
2019-04-12
>
samedhi00:04:16

I have something that looks like this in advanced compilation (first is (js/console.log %) second is (js/console.log (pr-str %))

samedhi00:04:09

It is supposed to be a transit bigdecimal (I think). How do I get a bigdecimal representation out of this? Or, if not possible, how do I get just the value in ka reliably.

samedhi00:04:26

I know I can (aget obj "ka"), but I am not sure that is stable under advanced compilation.

mfikes02:04:29

@samedhi It should be the rep field, so (.-rep x)

henrik08:04:21

How do you deal with the HTML5 history API? I have a search app (re-frame), and employ Accountant for history manipulation. You request a search, it goes and does it, and then sets the URL. Setting a URL, however, issues a dispatch to the search event. This is not an endless loop; it's short-circuited since the search event won't issue a search if nothing has changed. Still, I would like to avoid that second search. It's just useless. Is it possible with the history API to set a URL without dispatching it? Accountant itself doesn't offer this option as it turns out.

cjohansen10:04:24

I think I found a regression between ClojureScript 1.10.439 and 1.10.520. the following code snippet (reduced as much as possible) compiles fine under 1.10.439, but throws an exception on 1.10.520 during compile:

cjohansen10:04:27

(def ^:dynamic *remote* (when js/window
                          ""))

(cond
  *remote* (println *remote*))

cjohansen10:04:18

if you have a dynamic binding that somehow touches a js/* object and that binding is referred on both sides in the cond, compilation fails with:

cjohansen10:04:25

Failed to compile build figwheel-default-repl-build in 0.224 seconds.
java.lang.NullPointerException
        clojure.core$namespace/invokeStatic at core.clj(1603)
              clojure.core$namespace/invoke at core.clj(1597)
        cljs.compiler$emit_var/invokeStatic at compiler.cljc(448)
              cljs.compiler$emit_var/invoke at compiler.cljc(442)
        cljs.compiler$fn__3341/invokeStatic at compiler.cljc(489)
              cljs.compiler$fn__3341/invoke at compiler.cljc(489)
                clojure.lang.MultiFn/invoke at MultiFn.java(229)
            cljs.compiler$emit/invokeStatic at compiler.cljc(202)
                  cljs.compiler$emit/invoke at compiler.cljc(182)
           cljs.compiler$emits/invokeStatic at compiler.cljc(209)
                 cljs.compiler$emits/invoke at compiler.cljc(204)
           cljs.compiler$emits/invokeStatic at compiler.cljc(229)
               cljs.compiler$emits/doInvoke at compiler.cljc(204)
                clojure.lang.RestFn/applyTo at RestFn.java(157)
            clojure.core$apply/invokeStatic at core.clj(665)
                  clojure.core$apply/invoke at core.clj(660)
           cljs.compiler$emits/invokeStatic at compiler.cljc(210)
                 cljs.compiler$emits/invoke at compiler.cljc(204)
        cljs.compiler$fn__3828/invokeStatic at compiler.cljc(1382)
              cljs.compiler$fn__3828/invoke at compiler.cljc(1374)
                clojure.lang.MultiFn/invoke at MultiFn.java(229)
            cljs.compiler$emit/invokeStatic at compiler.cljc(202)
                  cljs.compiler$emit/invoke at compiler.cljc(182)
           cljs.compiler$emits/invokeStatic at compiler.cljc(209)
                 cljs.compiler$emits/invoke at compiler.cljc(204)
           cljs.compiler$emits/invokeStatic at compiler.cljc(223)
                 cljs.compiler$emits/invoke at compiler.cljc(204)
             clojure.lang.AFn/applyToHelper at AFn.java(160)
                clojure.lang.RestFn/applyTo at RestFn.java(132)
            clojure.core$apply/invokeStatic at core.clj(665)

cjohansen10:04:17

if you (let [remote *remote*]) and use the local binding on either side in the cond, it compiles fine, ditto if the var's original value does not involve the js namespace

cjohansen10:04:26

known issue, or should I report it in Jira?

todo10:04:36

Is there any work (even if not as well established as cider / cursive) on building a fully self hosting cljs IDE using Klipse ? [also pinging @viebel ]

mfikes11:04:41

@christian767 Probably the same as https://dev.clojure.org/jira/browse/CLJS-3068 If you are inclined to try the patch, it would help confirm that it is not a separate issue.

cjohansen11:04:04

@mfikes yup, works with that patch 👍

cjohansen11:04:31

glad I didn't have to debug that one, the behavior I experienced was pretty esoteric 😅

mfikes11:04:35

Thanks for checking! I suspect that, with the nature of the patch, a workaround might be to qualify the symbol used in the test. So, in your example, something like

(cond
  my.namesapace/*remote* (println *remote))

mfikes11:04:59

This sucks, but is the most minimal change I can think of to work around.

cjohansen11:04:59

I used a let, which worked also

mfikes11:04:20

Yeah, because then the test is on a local, which is another way to workaround.

mfikes11:04:44

Bad bug. Ugh.

cjohansen11:04:52

yeah, not good

cjohansen11:04:55

awesome work though 🙂

mfikes11:04:54

Thanks for reporting! Vote for the ticket. Otherwise I suspect it will be going through relatively soon regardless.

cjohansen11:04:53

I'm also seeing intermittent "can't take macro clojure.core/and as value" errors in code that has worked for a long time after upgrading to 520

cjohansen11:04:10

e.g. in (when (and js/window.something js/window.someOtherThing ...))

mfikes11:04:16

I think that's a Figwwheel issue

cjohansen11:04:31

I suspected as much, as it's not consistent

mfikes11:04:51

I thought it had been isolated to Figwheel; I don't see any tickets on it though.

David Reno14:04:32

I’m just learning ClojureScript. One thing I can’t sort out in my head is the repercussions of translating from Clojure to JS vs Clojure to JVM bytecode. The latter seems OK because it’s at least VM machine code. However, I’m concerned about the problems that may come up when going through another high-level language (i.e. JavaScript). Has any one written about the practicalities of this and provided arguments for why it’s OK or not-OK? Keep in mind, I’m not an expert, I’m just trying to sort-out if I like the philosophy or not before diving in. Some things I’m concerned about: • debuggers keeping track of the right instruction executing • debugging through two languages (do people sometimes need to read the JS to understand an issue?) • source code management: is the emitted JS an artifact that needs source control? • readability when uploaded to places like AWS Lambda

👍 4
nwjsmith14:04:42

I believe Source Maps address your first and second point (https://clojurescript.org/reference/source-maps). IMO treat the emitted source code the way you would treat binaries or JAR files. As far as readability of the compiled output, you’re probably going to have a bad time. ClojureScript isn’t CoffeeScript. The Google Closure compiler does some fantastic optimizations that result in inscrutable output.

David Reno15:04:18

source-maps are relevant to the first two points, but they don’t address them. My simple understanding of source maps is that they are the link to what JS is related to what Clojure and are used to show which clojure line is related to the current debugger step. This may be all academic, it might be that all bugs can be solved that way and no one ever has to look at the JS. For the second point on generated JS (again maybe academic only), as CLJS and Goog Closure are surely changing, presumably recompiling the same Clojure could result in different JS that might cause different behavior? For the readability item, I only mean that in AWS Lambda, when looking at a function, you can see the code. This will present the optimized JS instead of the language that the programmer used; less than ideal.

nwjsmith16:04:54

I hadn’t considered the possibility the compiler would produce different output for the same program. https://github.com/binaryage/dirac is some tooling that makes debugging ClojureScript programs similar to debugging JS programs in the browser. That being said, there have been ClojureScript compiler bugs that probably required dipping into the compiled output. That Lambda output thing is tricky. Wonder if you could wire up a simple browser extension to use source maps on that…

Stefan14:04:39

@dcreno I loved this talk: https://www.destroyallsoftware.com/talks/the-birth-and-death-of-javascript, it’s quite related to your question regarding considering JS as a programming language vs bytecode.

David Reno14:04:25

thanks, I’ll have a look. I see it’s 5 years old now but I’ll assume still relevant.

👍 4
David Reno14:04:54

and maybe biased because it’s from PyCon? 😉

Stefan14:04:21

🙂 I think it’s a inspiring vision that he presents!

nwjsmith16:04:16

Macros aside, will the same ClojureScript program compiled with the same version of ClojureScript result in the same JavaScript output?

john16:04:33

The minification process is non-deterministic

victorb16:04:34

AFAIK, Google Closure Compiler should be deterministic

john16:04:46

hah TIL... Not sure if I'd depend on it though in CLJS

victorb16:04:10

I can't think of a reason why the compilation process wouldn't be deterministic, as long as you're not doing IO/side-effects when it's doing the reading

john16:04:16

I guess from a cache invalidation perspective, you could use that level of determinacy. But I think minor changes will probably cause large changes to munged name mappings. Enabling :stable-names true in the compiler options will reduce name churn between advanced compiles.

martinklepsch16:04:36

Yeah, I guess the question would be if the CLJS compiler output is deterministic. And with gensym and things like it I'm not so sure about that.

martinklepsch16:04:00

Also notice that in the mailing list post above the OP mentions simple optimizations and not advanced which is what you'll usually use. Closure might still be deterministic but these messages aren't about exactly the same thing that we do in ClojureScript.

dnolen17:04:32

@victorbjelkholm429 more or less I think modulo gensym as mentioned

dnolen17:04:43

I think your comments about source mapping are perhaps a bit theoretical and don't really translate to practice - hardly anyone is debugging the generated source

dnolen17:04:09

that said we didn't have source mapping for almost 2 years - so that's what people used to do

dnolen17:04:46

since the code we generate is very regular it's possible to do - but it does take some getting used to

dnolen17:04:45

it gets harder of course if you're using a code transformation heavy thing like core.async a lot - which you probably shouldn't do anyway 🙂

dnolen17:04:52

anecdotally I don't see many complaints about debugging ClojureScript so I think source mappping + cljs-dev tools are probably working pretty well for most people

👍 4
athomasoriginal18:04:02

I have a small UI library I am working on. I would like to control the surface area of my API so instead of developers having to import components like this:

[ui-lib.components.comp-1 :as comp-1]
[ui-lib.components.comp-2 :as comp-2]

comp-1/comp-1
comp-2/comp-2
They could just do
[ui-lib :as ui]

ui/comp-1
ui/comp-2
To do this I create an entry point in my library and alias them like this:
(ns ui
  [ui-lib.components.comp-1 :as comp-1])

(def comp-1 comp-1/comp-1)
I believe this style will fail to preserve the metadata and docstrings and hurt users IDE experience. Is there anything I can do to preserve these things? Based on some other readings I also feel this goes against clojure philosophy

dnolen18:04:29

I would move the metadata and docstrings to the API ns

dnolen18:04:52

migrating that stuff across nses by other means is yucky IMO

athomasoriginal18:04:05

Thanks! Would you say what I am trying to do is something generally discouraged?

lread18:04:21

@tkjone, there is potemkin import-vars for clojure. As a learning exercise, I am porting this to cljs within the context of rewrite-cljs (not done yet). But I would listen to @dnolen, I’m just learning, he’s the wizard.

athomasoriginal18:04:28

Nice! I was actually looking at Zach’s work. Excited to see what you come up with 🙂

lread18:04:20

It is kind of ridiculous the amount of time I have spent on this. But all good learning!

athomasoriginal18:04:07

For sure. Would love to see a blog post on the learning!

lread18:04:29

I’m enjoying the learning but questioning the work! I don’t want to promote a questionable pattern. :thinking_face:

athomasoriginal19:04:12

haha I hear you!

athomasoriginal18:04:15

@dnaeon Thanks! I agree, I did not want to go too far down that path at this point. Would you say this, reducing the API surface areas as I am doing, is going against idiomatic clojure, or its just a preference thing that is fine to explore in moderation?

dnolen18:04:21

reducing the api surface is a fine goal

dnolen18:04:36

but I think manually putting that api surface together is fine

👍 4
dnolen18:04:40

I don't know why people need tools for this

dnolen18:04:49

if the api surface was huge like AWS or something I would use codegen

dnolen18:04:04

and not bother with vars or macros

lread18:04:37

After working on the cljs version of this for a while, I think I see your point. When there is a problem with the magic macro, a lot of time can be wasted.

dnolen18:04:18

if I recall, I think Zach might have originally created import-vars for dealing with OpenGL - which has a similar surface issue - but import-vars is just one way to deal with that problem - and not obviously a good one to me