This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-07-28
Channels
- # asami (1)
- # aws (9)
- # babashka (16)
- # beginners (32)
- # calva (2)
- # clj-kondo (20)
- # cljdoc (6)
- # clojure (35)
- # clojure-dev (25)
- # clojure-europe (11)
- # clojure-india (1)
- # clojure-norway (2)
- # clojure-spec (26)
- # clojure-uk (1)
- # clojurescript (41)
- # conjure (3)
- # css (9)
- # cursive (18)
- # data-oriented-programming (6)
- # data-science (2)
- # emacs (47)
- # events (1)
- # fulcro (15)
- # graalvm (30)
- # gratitude (7)
- # honeysql (27)
- # inf-clojure (4)
- # introduce-yourself (2)
- # lsp (129)
- # malli (7)
- # missionary (21)
- # nbb (17)
- # off-topic (18)
- # re-frame (6)
- # releases (1)
- # shadow-cljs (120)
- # vim (7)
- # xtdb (15)
Just to check, is (defprotocol p (f ^ISeq [_]))
supposed to be supported? It exhibits the same error as CLJ-1180 on 1.11.1.
Just on the topic of protocols, in trying to make some things more performant, I just came across https://clojure.atlassian.net/browse/CLJ-1814`satisfies?` - is there any chance that would be looked at for a near release?
It says it is waiting on https://clojure.atlassian.net/browse/CLJ-2426
The following tickets are being considered for 1.12: https://clojure.atlassian.net/issues/?filter=10032
Neither of those satisfies?
tickets are on that list.
I think the push back has been "if you're using satisfies?
you're already circumventing type-based dispatch so you're not on the performant path at that point"...?
Eh, huge facepalm on me for not noticing that it’s waiting on 2426…, thanks for the clarification
That fast path thing is interesting. I saw satisfies?
checks used to decide whether you can switch to a faster path but perhaps there’s a better way there
But if there is, I don’t know what it is. Tried the following just now, but looking at it now it was silly of me to even think it could work:
(ns user)
;; not under my control
(defprotocol FastPath
(do-fast-path [this arg]))
;; under my control
(defprotocol SupportsFastPath
(supports-fast-path? [this]))
(extend-protocol SupportsFastPath
nil (supports-fast-path? [_] false)
Object (supports-fast-path? [_] false)
;; need to put a type here so using the interface
;; that the protocol generates
user.FastPath (supports-fast-path? [_] true))
(extend-protocol FastPath
;; but this obviously won't make
;; implementers of IPersistentMap also implement user.FastPath...
clojure.lang.IPersistentMap
(do-fast-path [_ arg] arg))
(comment
(supports-fast-path? nil)
;; false
(supports-fast-path? 1)
;; false
(do-fast-path {} :fast)
;; :fast
(supports-fast-path? {})
;; false unfortunately
(satisfies? FastPath {})
;; true but slow
)
So some logic could go onto the fast path but it needs to check whether the data is has supports the fast path. Checking with satisfies?
is slow. Is there another way I’m missing perhaps?
I've not read closely, but I believe one pattern for this kind of thing is to have an implementation of your protocol for Object, and then when you land into that implementation call extend-protocol
I’m not sure how that would work. Here’s my case a bit shortened:
(defn supports-fast-path? [x]
(satisfies? ThirdPartyProtocol x))
(if (supports-fast-path? input)
(fast-path input args)
(slow-path input args))
This is library code. The only thing I can assume is that if input
implements ThirdPartyProtocol
then I can go down the fast path. I have no control over what input
is or how it implements ThirdPartyProtocol
which I also don’t have any control over.You extend SupportsFastPath to Object, and if the object you have satisfies ThirdPartyProtocol you extend it's class to SupportsFastPath.
The point I was trying to make with the example is that satisfies?
should not be dismissed as “you’re already on the slow path if you call it”