Fork me on GitHub
Kevin Lynagh01:11:31

I'd like to swap out a few functions between a "development" build and a "production" build of a cljs program. Think using (foo-with-instrumentation x y z) in dev and (foo x y z) in prod. The only way I can think of doing this is to use goog-define vars:

(def foo (if DEV? dev-impl/foo-with-instumentation impl/foo))

Kevin Lynagh01:11:24

where the value corresponding to DEV? can be changed w/ the :closure-defines cljs compiler option.

Kevin Lynagh01:11:53

However, since the instrumented functions live in a different namespace than the uninstrumented one, does this mean I need to pull in those namespaces with toplevel require rather than in the ns form?

Kevin Lynagh01:11:54

Not sure if this is the best way to go about things, or if there's a neater solution.


@kevin.lynagh top level require is basically the same as ns. it can’t be conditional either. you add a :preload in dev that just uses set! to change the impl of foo.

Kevin Lynagh06:11:17

Got it, thanks for the reply. I'm nervous about the idea of using set! lest I forget to override every var. I'm going to try having identical namespaces and choosing between them via source-paths.


@kevin.lynagh i wouldn't call it neat but you could have two directories which each define the same namespace, dev/my/foo.cljs and prod/my/foo.cljs, then set the source paths in the dev/prod profiles

Kevin Lynagh06:11:27

Yeah, this sounds like it might be the easiest way forward. I've done this hack in the past. Thanks!


I'm having a weird bug, and I have no idea how to track it down. I have a SPA where I use hash urls (/index.html#/foo), and some radio inputs in a form. well for some reason, when executing an event (which only updates an atom) my whole page gets reloaded as /index.html?bar=baz#/foo, where bar is the name of the radio group, and baz the value of chosen radio input. Any idea how to track down the code that is reloading my page? (breakpoints on global events like onbeforeunload will not show me a relevant stack trace)


@roti, the form gets submitted?


its a simple onlick event with a function that just swaps an atom (after which the dom gets rerendered)


try adding onsubmit="return false" to your form, just for shits and giggles


@pesterhazy now it works fine 🙂 great idea, thanks


so the form got submitted, by why?


I meant, how could I find out why the form is submitted?


How do I pass a clojurescript function to a JS function that expects a callback? Do I have to convert it somehow or is it toll-free bridged?


try planck -v and enter (defn foo [n] (* n n)) - you'll see what it compiles down to


For an even simpler (Var-free) view of things see what you get without the def. Evaluate (fn [n] (* n n))


👍 for planck -v - very useful to explain stuff to beginners with solid JS knowledge


thanks for adding this!


(FWIW, def forms only evaluate to Vars while in the REPL.)


is there a collection function (or combination of) with which I can search in a vector (using a predicate) and get the index? but without going through the whole array. I need something like some which returns the index


@roti reduce-kv and then use reduced


AFAIK, there is no core fn for this. Andre is right, and there are others at


reduce-kv traverses the whole collection, doesn't it?


@roti The use of reduced should prevent traversal of the whole collection. A concrete example

  (fn [_ k v] 
    (prn k) 
    (when (= v :c) 
     (reduced k))) 
  [:a :b :c :d :e])
^ Edited to show steps via prn


I like the example of (count (take-while (partial not= item) coll))) for this.


@ajs Yeah, I suppose the reduce-kv variant might be faster if you are dealing with vectors, while your example is generic for sequences. I think you can get a backtick by holding down the tick key.


The long press worked, thanks!


reduce is explicit iteration which I try to avoid as much as possible if there are other functions available


does anyone know of a starter repo for leiningen + es6 modules


i know it's alpha but I wanted to play around with it a bit I can't get the basic example working from the blog post, i don't know what i'm doing differently


@ajs @roti I was curious about the perf of reduce-kv on vectors vs. generic seq fns. Here is a result:


Very cool. How did you do the benches?


yes, indeed. very interesting.


@ajs If you set up the ClojureScript compiler for running tests (see, then you can run ./script/benchmark. With that, it is an easy matter to modify this file to include new tests that you might be interested in, and it will run them across all of the JavaScript VMs you've set up. You can also delete everything from line 11 down, and replace it with just the benchmarks you want to run.


One bit of advice is to watch out for benchmarking expressions that Closure can completely optimize away. (Sometimes you need to "let" a fn containing the expression of interest in the simple-benchmark binding portion and then call it in the body.


I just discovered simple-benchmark in cljs, so for less aggressive benchmarking, that will probably help me test little functions like this in the future


@mfikes @rauh thanks, I was planning to join the values with their indexes and then use some, but I think reduce-kv is better


Yeah, it is all just tradeoffs. If you concretely know you are operating on vectors, you can play games like this. 🙂


nvm git it to work with figwheel


does clojurescript have any mechanisms similar to user.clj that would let me monkeypatch things before the primary code runs?


Thanks! I thought there was some weird thing going on but in the end the clojure syntax was obscuring (to my untrained eye) my misuse of the JS API :)


I use try/catch in a go block and it doesn't seem to catch. am I doing something wrong?

(defn testex  []
      (let [response (<! (http/get "" {:with-credentials? false}))]
        (println response))
      (catch :default e
        (println "error" e)))))


@roti any channel op breaks out of the enclosing try


erm, try is inside go


core.async is turning what looks like sequential imperative code into a bunch of callbacks - the exception is inside your callback


@roti it is, but your <! contains an http/get that is not inside your try 😄


it's actually a callback, for readability sake core.async makes it look like it is


so I should try inside the <! calls?


if that's where you expect the exception, yes


ok, thanks


or, another way to put it is that if http/get is the thing throwing, it should have a try around it


I think... but http/get is giving you a channel which makes me think things might be trickier than that...


I would need to read the code to help more at this point I think


let me try putting it around http/get


@pontus.colliander that's very helpful advice, and if the authors of the http lib roti was using had followed it, roti would not have this problem


@noisesmith nope, doesn't work. here's the code:

(defn testex []
    (let [response (<! (try (http/get "" {:with-credentials? false})
                            (catch :default e
                              (println "error" e))))]
      (println response))))


the answer here might be using a different lib, or a PR to fix the one you are using


so, http/get returns a channel, which apparently is not happening when an error occured (in my case the response is of type json, but the content is not so http can't parse it, so it throws an error)


it looks like a bug in http to me


which http lib is it?


actually I'm not so sure where the error is thrown, because if the channel is not returned because of an exception, it should be caught.


Uncaught SyntaxError: Unexpected token S in JSON at position 0 at JSON.parse (<anonymous>) at cljs_http$util$json_decode (util.cljs?rel=1509894674732:63) at core.cljs:4829 at Function.cljs.core.update_in.cljs$core$IFn$_invoke$arity$3 (core.cljs:4829) at cljs$core$update_in (core.cljs:4820) at cljs_http$client$decode_body (client.cljs?rel=1509894676467:83) at Function.<anonymous> (client.cljs?rel=1509894676467:181) at Function.cljs.core.apply.cljs$core$IFn$_invoke$arity$2 (core.cljs:3685) at cljs$core$apply (core.cljs:3676) at async.cljs?rel=1509880110795:712 cljs_http$util$json_decode @ util.cljs?rel=1509894674732:63 (anonymous) @ core.cljs:4829 cljs.core.update_in.cljs$core$IFn$_invoke$arity$3 @ core.cljs:4829 cljs$core$update_in @ core.cljs:4820 cljs_http$client$decode_body @ client.cljs?rel=1509894676467:83 (anonymous) @ client.cljs?rel=1509894676467:181 cljs.core.apply.cljs$core$IFn$_invoke$arity$2 @ core.cljs:3685 cljs$core$apply @ core.cljs:3676 (anonymous) @ async.cljs?rel=1509880110795:712 (anonymous) @ async.cljs?rel=1509880110795:702 cljs$core$async$state_machine__29062__auto____1 @ async.cljs?rel=1509880110795:702 cljs$core$async$state_machine__29062__auto__ @ async.cljs?rel=1509880110795:702 cljs$core$async$impl$ioc_helpers$run_state_machine @ ioc_helpers.cljs?rel=1509880107319:35 cljs$core$async$impl$ioc_helpers$run_state_machine_wrapped @ ioc_helpers.cljs?rel=1509880107319:39 (anonymous) @ ioc_helpers.cljs?rel=1509880107319:48 (anonymous) @ channels.cljs?rel=1509880106192:61 cljs$core$async$impl$dispatch$process_messages @ dispatch.cljs?rel=1509880105746:19 channel.port1.onmessage @ nexttick.js:211


> actually I'm not so sure where the error is thrown, because if the channel is not returned because of an exception, it should be caught. if the error is thrown inside someone else's go block, your try/catch cannot catch it


and if core.async runs the code that throws the error before the code that uses the channel, you never see the evidence the channel got returned


IMO there's little reason to use a library for HTTP requests in CLJS. Just use js/fetch


I'd also recommend against introducing core.async unless you have a serious need for its features


cljs-ajax has convenient support for transit


@pesterhazy RE core.async > I'd also recommend against introducing core.async unless you have a serious need for its features Would this include using it to create functionality like that produced by setInterval?


@tkjone, I can’t imagine creating an clojurescript application in the browser without core.async. I think it’s an easier way to deal with the event handling and callbacks that are apart of most js apis


including creating functionality similar to setInterval (probably using timeout from core async)


That was also my impression, but I wanted to see under which cases core.async is "too much"


@tkjone yes of course, why would using setInterval necessitate the introduction of macros and channels?


that’s just the way i’m most comfortable. I’m not saying it’s the right thing everyone


I’ve already gone through learning some of the quirks of core async


so I just start with core async at the beginning


by the way, often using would be a good alternative to using setTimeout directly


if you’re working on a project with a team, there is somewhat of a barrier to entry with picking up core async, so using goog.Timer or setTimeout directly is definitely more straightforward


the macrology involved with core async can also make debugging more difficult.


I'd argue core.async has a high cost even in a team that knows it well


yea, i prefer using core async, but I totally get that many would avoid core async unless it’s doing a lot of heavy lifting


This is one of those interesting things about learning CLJ/S: There are a lot of mechanisms that are capable of doing the same things, but not all of them should be used in all scenarios. I think this might present itself a little more in CLJS because, it feels to me, that the interop is used more often in CLJS.


Earlier today I was prompted to write something like this:

      (loop []
        (async/<! (async/timeout 16))
Because I figured it was more idiomatic than the simple js/setInterval (had no idea about goog/timer) This is not to say that other languages do not have this issue


core.async has pros and cons, but i wouldn't use it just because it's idiomatic (I'd argue it isn't, not on the server and especially not in the browser)


This is interesting because I feel that I have read quite a bit about the language and still find it challenging to find out what the right tool for the job is. My example was idiomatic setInterval, but this also applies to other areas like .. v. -> macro etc


I agree, a lot of this is tribal knowledge


.. being deprecated-ish in favor of ->


from the outside it may look like everyone in clojure(script)land is using core.aysnc, but that's far from true


See, I did not know this. .. is often passed on as an okay practice, which I am sure it is, but as you mention -> is likely better practice. And yes, core.async does seem to be widely used


The question is, how can the tribal knowledge be accessed?


people blog, or give talks


but I agree that this knowledge, or experience, is not easily accessible


would you say other communities do a better job at this?


I find that it's worse in JavaScript, because some of the material you find online is written by novice programmers, so you need to watch out for signs that the author doesn't really know what they're talking about


haha True and I accept that answer because it is true. With this in mind, if all developers are working on different teams, the tribes split and evolve and grow. How do we keep track of the evolution? Yes, I believe that the Python, Go and JS communities do an excellent job of this this. Emphasis on JS. JS has other issues, but it is very easy to find what all the tools are for one task, and find write ups on when to use them.


I also agree about writeups from novices


I have been steered in the wrong direction several times because of this. This is both in JS and Clojure, but with JS you know the 10 most reputable developers and you can use their work to vet others writings


In Clojure, I know the reputable developers, but their writings, valuable as they are, are sparse


agree with that


but you need to understand that python, js etc. are orders of magnitude larger than we are


Definitely true. This is understood.


I'd like to blog more, but it's hard work and you don't immediately see the effects


I hear you. What would you say is a good approach to asking the clojure community to support efforts that attempt to share the tribal knowledge. Essentially asking people to peer review your writings? I generally just ask whichever channel I believe would be able to contribute, but there is a line and I want to be sure its not being abused


I know we have the community driven API docs, but I find that those make assumptions about learning styles and also context is not given so understand things like when to use one tool over another


personally I'm always happy for people to ask for feedback on the writing


I think most clojurians feels the same


Yes, I have only had positive responses thus far. Whatever I have said about CLJ/S at large, this forum is likely one of the best I have ever experienced. So CLJ/S is a friendly tribe


Here is a fun one. I am working with an experimental browser feature: webkitSpeechRecognition. When you speak, you are going to get back a SpeechRecognitionResultList which is distinct because it is not an Array. Here is some sample code:

(set! js/SpeechRecognition (.-webkitSpeechRecognition js/window))

(def recognition (js/SpeechRecognition.))

(set! (.-interimResults recognition) true)

(defn handle-speech
  (map (fn [results] (get results 0)) clj-results)

(.addEventListener recognition "result" handle-speech)
This will error out when you try to speak into your speaker with Uncaught Error: [object SpeechRecognitionResultList] is not ISeqable. I ran into something similar with nodeList and I was able to resolve it with a protocol like:
(extend-type js/NodeList
   (-seq [node-list] (array-seq node-list)))
However, this won't work for the above, because there is no JS/SpeechRecognitionResultList object.


I don't understand the snippet. Where's e used?


Anyway can't you just use array-seq directly?


also it looks like you're using map for side effects. Don't do that. Use doseq or run!


Sorry, e was a mistake. It should be results


(get results 0) would be a side effect?


no but... handle-speech is an event listener, so its return value is presumably ignored?


Oh, yes, 100%. Sorry, I will be storing the value returned by Map and doing some more processing in the future. But right now, I was just running some tests and wanted to illustrate the problem. Good point though!


anyway try (->> results array-seq (map ...) prn)


Hello, a question about advanced optimization: I am using D3.js in CLJS, and have a D3 callback function (the anonymous function below) that receives a previously bounded data as input from D3. Without advanced optimization, I get the expected numeric value in minutes, but with optimization, I get undefined. Any ideas?

(.attr "transform"
                  (fn [d i]
                    (let [minutes (.-minutes d)
                          y (y-scale minutes)]
                      (str "translate(0, " y ")")))))


I am completely new here, but I have some experience with the Closure Compiler. Perhaps the optimizations are renaming the minutes property during minification?


ah. is there a way I can avoid the renaming? Also, wondering if I can avoid writing problematic code like this


hmm, doesn't look like it AFAICT. just logging with _ (js/console.log (.-minutes d)) gives me undefined


In JS world, using brackets to access a value eliminates it as a candidate for renaming. So d['minutes'] would be safe.


I think in that case it is still possibly minifying the '.-minutes' part


I would inspect the js output maybe to see if that's the case


In terms of a Clojure-y way to represent bracket syntax, maybe using (:minutes d) would work? I'm a newb here coming from JS land, so this is just a guess.


Hmm, that doesn't seem to work. Maybe using aget? But that might just be equivalent to .-


Looks like this page outlines a solution you can use. Simply put: (aget obj "propertyName")


@U7W5MHG1L that does work, thanks much!


- if I log d above it gets printed as {minutes: 20} etc. - I am using D3.js from CLJSJS