Fork me on GitHub

how do I write something like this with js interop? this.xAxis[0].ticks[20]


@restenb (this-as this (-> this (.-xAxis) (aget 0) (.-ticks) (aget 20)))


@thheller worked perfectly, thanks!


Hi, just switched to spacemacs and cider. Is it possible to use clj-refactor,refactor-nrepl with clojurescript? To e.g. rename symbols. So, clj-refactor is working, it just says that it is only working with .clj files. Is piggieback for this use case? I'm using shadow-cljs and only added :nrepl {:port 9000 :middleware [refactor-nrepl.middleware/wrap-refactor cider.piggieback/wrap-cljs-repl]} The dependencies are injected via -d parameter.

Lone Ranger13:08:48

@bitkiller.42 some of it works for me, a lot of it doesn't 😕 sometimes switching to clojure-mode works for somethings, sometimes it doesn't. If anyone has a good answer to that I'd love to know.

👍 4

Is there any good implementation of ADTs + core.match in CLJ(S)?


people messed with that, I'm sure there are some old libraries around on GitHub

Lone Ranger17:08:42

ADTs? :thinking_face: what's that?


it's popular in typed functional programming languages - but I wouldn't call it an idiomatic programming pattern for Clojure

👍 4

Is there a good resource/reference for "idiomatic" Clojure?


there's tons of books and online resources


Clojure Programming, Joy of Clojure are good places to start

Lone Ranger18:08:39

that is actually any interesting gap in some ways. As in, sometimes I'll end up doing something like this

(defprotocol ISomething
  (do-it [this]))

(extend-protocol ISomething
  (do-it [this] ...)
  (do-it [this] ...)

when really I'd like to dispatch on abstraction. If it implements associative, do this, if it's like a keyword, do this, etc... vs going on concrete types

Lone Ranger18:08:32

can't quite figure out how to do it with a single multimethod either, so the code ends up becoming rather ineligant

Lone Ranger18:08:19

I haven't figured out how to use hierarchies in multimethods yet, perhaps that would solve my issue.


Can’t you write a multimethod that checks to see if the input is associative?


(defmulti foo associative?)
(defmethod foo true [val] (println "Associative!"))
(defmethod foo false [val] (println "Not associative!"))

user=> (foo 3) 
Not associative!
user=> (foo {:a 3})

Lone Ranger19:08:54

certainly, but that breaks down when I want to dispatch differently, on, say, keywords, sequences, strings, and associative structure. I.e., let's say my final goal is

{:event some-event :data some-data}
and I want to make the public API such that it works with (event! :some/event) (if no data is required for the event), (event! :some/event "some data") for double arrity, (event! {:event :some/event :data "some data"}) for a fully formed event, (event! [:some/event "some-data"]) for vector style dispatch, and perhaps (event! (stream-of-events)) which is an infinite sequence of events.

Lone Ranger19:08:11

you might say, "hey, you're doing too much!" ... and you might be right. It is solved pretty well using a combination of protocols (for type-based dispatch) and then multimethods (for data based dispatch), but the protocols seem to come with a good bit of redundancy and an overall lack of extensibility. I.e. if someone is using a tree structure with my API, as long as they implement the associative?, I'd like them to be able to use it.

Alex Miller (Clojure team)19:08:45

one trick for this in clj (which may totally not work on cljs) is to extend a protocol to Object, then have the Object impl do whatever detection it needs (associative? etc) on the value, then dynamically extend the protocol to the concrete impl it happens to have in hand, then reinvoke the protocol method, which will now route to the new handler. this is a one-time thing (per concrete type) as all subsequent calls take advantage of the dynamically installed handler

Alex Miller (Clojure team)19:08:35

but I kind of assume the dynamic thing doesn't work in cljs

🤯 8
Lone Ranger19:08:49

It might but I'm going to have to meditate on that!!! Sounds like a dynamic, recursive protocol which is awesome

Alex Miller (Clojure team)19:08:29

it's not recursive, as you make either 1 or 2 calls, never more

Alex Miller (Clojure team)19:08:29

this actually came up, on stage, at the very first conj. Chouser was a doing a talk about the brand new protocols and took a question about this case, and Rich chimed in from the audience

Alex Miller (Clojure team)19:08:05

I wrote it up in more detail in Clojure Applied btw

Lone Ranger19:08:16

ohh!!! to the book shelf!

Lone Ranger20:08:33

... you're telling me Rich made this up on the fly in response to a question...?

Alex Miller (Clojure team)20:08:39

I had the impression that he had already figured it out, it just wasn't obvious to anyone else :)


@alexmiller that's actually possible, I'd forgotten about that trick

Lone Ranger20:08:10

Dang Rich leave some code for the rest of us!!!


since it's JS you could modify the prototype on the fly in the default handlers which is the corresponding pattern for Object in Clojure

Lone Ranger20:08:17

(╯°□°)╯︵ ┻━┻


there's a lot of details so I would definitely put this in the advanced tricks camp

Alex Miller (Clojure team)20:08:30

I've run into it multiple times in Clojure, usually when I want to build a protocol that partitions according to some other protocol


would react hooks in clojurescript simply be something like

(defn local-state [initial-value]
  (let [val (atom initial-value)
        get-fn (fn [] @val)
        set-fn (fn [v] (reset! val v))]
    [get-fn set-fn]))
probably with something to notify on change somewhere?

Lone Ranger23:08:34

is this like, in a hypothetical world where we didn't have frameworks like reagent? I mean, it's certainly a higher order function with mutable encapsulated local state, which is kind of like a "class"/"object", so in that sense I can see how it would be similar to a React class, but I think the primary differentiator of a React class is how those hooks are interpreted by the react machinery.

Lone Ranger23:08:02

So, kind of yes?