Fork me on GitHub

what would something like this look like in cljs?


var tree = d3.tree().size([height, width - 160]);


i tried variations of (.tree js/d3), (-> js/d3 .tree .size ..) etc


if anyone could point me to a good resource for js interop i would be grateful as well


would it be (-> js/d3 .-tree etc etc)


i’ll check that link out , thanks


both links very helpful, thanks!

Drew Verlee02:07:33

how would you go from [{:m 1} {:m 2}] to [1 2] and at meta level is there a better way to figure this out then ask in #C053AK3F9 ?

Drew Verlee02:07:30

also how light weight is specter? does it make sense to pull it in for small tasks like that or only when you feel the pain?


You have a sequence of two things and you want a sequence of two things as a result — and the way to get from each thing to each result is the same "transformation" — so this would be some application of map.


(if you specifically wanted a vector as a result, use mapv)


Does that help with the meta question?

Drew Verlee02:07:37

yea, im not sure why i didnt think i couldnt do it with map


For something lightweight like that problem, I’d rely on built-in (core) functions.


{:m N} -> N is the "function" :m (realizing keywords can be used as functions is a "lightbulb" for a lot of beginners)

Drew Verlee02:07:46

yep! I think its also i sign that i need to get to sleep sense i did that 30 minutes ago for something else 😕


Internalizing how to identify common low-level tasks and work with sequences / collections and the (vast array) of core functions just takes time and practice… Even after five years of production Clojure, I’m still "discovering" new core functions and reading and re-reading a lot of the basic stuff about abstractions and so on.

Drew Verlee02:07:30

I wonder if their are non clojure specific ways to train

Drew Verlee02:07:54

* => & & & map!

Drew Verlee02:07:40

sort of strip out the words and parens and just leave the transformations as a visual

Drew Verlee02:07:00

maybe that breaks down at some point...


I need to create a bunch of dates of type #inst because I want to insert them in Datomic. I concocted this way but there must be a better way!

(require '[clj-time.coerce :as c])

    (defn random-instant [limit]
        (c/to-date (c/from-long (long (rand-int limit)))))


Sounds like a job for generators in clojure.spec 🙂


would it make sense for API calls to end with a ! for either query based or an operation that causes an effect on the API end?


frame of mind from ruby it seems that functions ending with ! would imply some kind of state being mutated outside the context of the function


Personally (and I haven't written that much clojure, but I've written a fair bit of Scheme, which has similar conventions) I wouldn't use bang for that.


On some level you program is going to cause side effects in the outside world (unless you're running it to heat up your room a bit in the winter)


That's something you should be very careful about, actually, so bang seems like too much and too little at the same time.


the problem as well is that there is some heavy rate limiting going on, so the code will sleep on a thread to not hit those limits


(on the query aspect)


also if you're going to do something like send a tweet, you kinda have sent a mutation outside your system, and it wouldn't let you call it again


i'm not really sure if that is considered unsafe in STM since i don't fully understand it right now


@naomarik: it is a very tough one to choose, generally I don't mind having ! in functions as general warning that...something is going on within it and I should check the docstring or the source to understand what it is. So in this case I would put it. In this SO thread it cites IO as well


at the end of the day it is just a convention so you can make your own I guess


the STM bit of it is there because STM code is retried over and over until it succeeds (ok not quite, but bear with me)


so a function like the above, which would do IO (maybe keeping counters) and even block threads, would be considered unsafe in STM


all this, IMHO of course


I think traditionally the ! is used to denote that the function is changing state


@pcbalodi: i would have thought so too, but the clojure style guide is pretty specific about the STM


which is something i don't understand myself so i have no clue how to create a mental model of when to use it


changing state is an easy thing to see


@naomarik: The STM reference is along these lines: consider an expression that looks like it calls a function once but behind the scenes it might actually call that function two or three times. Would you be able to detect how many times it called that function? If so, the function should have ! to indicate it is "multi-call unsafe" in some way...


That said, there’s a balance to be struck between sticking ! on everything that might yield a different result on each call vs just those that modify the system in a "destructive" manner.


It’s why, for example, java.jdbc has query (no !) but insert! and update! (and execute!).


Technically, query could return different data in subsequent calls, and you don’t really want an STM function to call a DB-accessing function repeatedly, but semantically that choice makes more sense.


(so, whilst the style guide is pretty specific about STM, there’s still quite a grey area there)


In case anyone is looking for a good book to help with learning Clojure past the basics, Clojure Applied is on sale right now and is a fantastic resource IMO.


@seancorfield: that's very useful thanks! what would you think about a function that has an effect outside the system (like replying to a user via an API), if all it does is simply one call and we don't care about the result?


@naomarik: What happens if it is called more than once (with the same arguments)?


That would be my determining question.


If it’s idempotent — calling it repeatedly with the same arguments has no additional effects after the first such call — then I would say it’s "harmless" to do so and therefore it wouldn’t need !. But in general calling "destructive" APIs that change the world sounds like something that wouldn’t be idempotent and would therefore deserve a !.


anyone used d3 with cljs before?


Yes, with Om and Reagent, but it was a long time ago… What’s your question?


Best I can point you at, based on my experience, is this: @krchia


I thought I had the rewritten Reagent version up on GitHub as well but apparently not.


i have a problem making a d3 call


i get "#object[TypeError TypeError: Cannot read property 'ctrlKey' of null]" from (.. js/d3.event -ctrlKey)


That example uses bare D3 in one example and NVD3 in another example, so take a look at the code and see if that helps you.


a direct translation from the js equivalent "if(d3.event.ctrlKey) return;"


you want (.. js/d3 -event -ctrlKey)


edited to show .event as field access followed by .ctrlKey as field access


i think both versions are equivalent, but i digress. i get the same error from your line of code as well


i get the error from the latest version of cljsjs


Perhaps you can put your code in a Gist or on and share the link here? Sounds like we need to see more of your code to be able to help you.


The error indicates that d3.event is null...


i’ll be happy to, but i’ve just been playing around in the REPL


i can do js/d3 calls to other classes properly, just not event


doing a human js->cljs translation of


i’m quite frustrated with this, it would be nice to do something like (dir js/d3)


I would assume d3.event is only going to have a value while you are processing an actual (keyboard?) event and so it will be nil otherwise?


All the cljs code I’ve seen that tries to reference (.. js/d3 -event …) only does so inside event handlers...


the js code i’m trying to translate to cljs is here


i didn’t quite think about that (that d3.event would be nil in the absence of output)


maybe i should just chuck it in my code and see what happens later on, instead of trying to verify that it’s a valid cljs expression in the REPL


And in that JS code the reference to d3.event is inside an event handler .on("mousedown", function(d) { if (d3.event.ctrlKey) return; …} )


Your REPL experiment verified that it is a field (not a function) and it has a null value:

cljs.user> (.-event js/d3)
cljs.user> (.event js/d3)
#object[TypeError TypeError: d3.event is not a function]


So you should not expect to be able to do (.. js/d3 -event -ctrlKey)


(i.e., not at the REPL top-level)


sigh.. it should’ve been so obvious


thanks so much 🙂


Working with raw D3 in cljs is pretty painful. So much interop.


That’s why I looked at NVD3 instead — dramatically reduced the amount of low-level boilerplate.


in what applications is cljs a win over js?


just curious, because im translating js to cljs line by line to gain some proficiency in js interop


The usual wins of immutability etc.


Translating JS to cljs is going to seem very painful, and probably produce much more bloated code.


Comparing an app built with cljs / Reagent to one built in JS / React is where you’ll see the big wins.


hmm, i think i’ll be better off for it if i can stick with this


i’m going to try and be stubborn with this for awhile, and try another approach if nothing’s sticking


Well, if you can subdue D3, that’s probably the worst interop mess you’ll have to deal with… so the rest should be a piece of cake! 🙂