This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-08-28
Channels
- # aleph (1)
- # announcements (16)
- # bangalore-clj (1)
- # beginners (78)
- # cider (109)
- # clara (3)
- # cljdoc (6)
- # cljsjs (3)
- # clojure (209)
- # clojure-dev (11)
- # clojure-europe (1)
- # clojure-france (9)
- # clojure-italy (13)
- # clojure-nl (3)
- # clojure-spain (2)
- # clojure-spec (19)
- # clojure-uk (50)
- # clojurescript (41)
- # clojutre (2)
- # core-async (45)
- # cursive (2)
- # datomic (14)
- # emacs (6)
- # figwheel-main (1)
- # fulcro (101)
- # graalvm (1)
- # graphql (3)
- # jobs-discuss (3)
- # kaocha (12)
- # leiningen (8)
- # music (4)
- # off-topic (47)
- # parinfer (8)
- # pathom (17)
- # pedestal (53)
- # re-frame (47)
- # reagent (22)
- # reitit (4)
- # shadow-cljs (49)
- # tools-deps (87)
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.
@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.
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
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
cljs.core.PersistentArrayMap
(do-it [this] ...)
cljs.core.PersistentHashMap
(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 typescan't quite figure out how to do it with a single multimethod either, so the code ends up becoming rather ineligant
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!
nil
user=> (foo {:a 3})
Associative!
nil
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.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.
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
It might but I'm going to have to meditate on that!!! Sounds like a dynamic, recursive protocol which is awesome
it's not recursive, as you make either 1 or 2 calls, never more
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
I wrote it up in more detail in Clojure Applied btw
ohh!!! to the book shelf!
... you're telling me Rich made this up on the fly in response to a question...?
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
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
(╯°□°)╯︵ ┻━┻
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?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.
So, kind of yes?