This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-04-20
Channels
- # ai (1)
- # announcements (4)
- # babashka (61)
- # babashka-sci-dev (14)
- # biff (15)
- # calva (34)
- # clj-kondo (43)
- # clj-on-windows (1)
- # clojure (123)
- # clojure-europe (31)
- # clojure-nl (1)
- # clojure-norway (8)
- # clojure-uk (4)
- # clojurescript (12)
- # code-reviews (2)
- # community-development (9)
- # core-async (3)
- # datahike (4)
- # datomic (61)
- # events (1)
- # graphql (3)
- # hyperfiddle (155)
- # introduce-yourself (1)
- # lsp (64)
- # malli (10)
- # pathom (10)
- # reagent (5)
- # reitit (6)
- # shadow-cljs (2)
- # tools-build (2)
- # vim (8)
- # xtdb (3)
@benjamin.schwerdtner Worked on the PR you started all day, it was a bit confusing :) There were a few things: metadata contains vars, not just symbols, I think? And comparing the vars from the host to the vars from SCI: this needed a deref, since they represent the same thing, but are not the same vars. • There are a few things left I think. In cider NREPL the :expects and :requires can be either vars or strings denoting "ops". I think it's nicer to not expose the middleware namespace directly but work with those string names and document those. (See https://github.com/clojure-emacs/cider-nrepl/blob/d219ce610d9030108c273fab933538fb3b24d8be/src/cider/nrepl.clj#L111) • See if we can really port one of the existing CIDER middlewares easily using the current state of things
This is my current agenda:
1. Try a few versions with either adapting xform middleware to handler style,
or modifying to handler style
2. Use the :nrepl.middleware/descriptor
metadata to build the middleware deps graph
(:expects, :requires etc.).
3. ? Split nrepl.transport protocols and make a sci nrepl Transport
Is it a matter of assoc'ing to the response?
4. Load the cider inspector middleware
5. run bb with inspector middleware
adapting would be using xform under the hood and having a layer that adapts handlers.
It would need a bit of work to make :expects
etc work.
I consider middleware->transducer
part of this layer already.
Modifying to handler style would be to not use xforms anymore, or to not use them for user middleware.
1a Yes, that's what's currently merged already right.
1b right, we could rewrite to handler style everything and drop the xforms OR support both, but mutually exlusively to not break existing users (cc @U7RJTCH6J)
Another option:
1c is to ask users to write in xform style.
Either way, I think we should not expose :ctx :msg :opts
to users, but only :msg
directly. The :ctx
is an implementation detail of SCI which should never be visible to bb users.
2. The sorting logic is already pretty much there, based on :expects and :requires logic. But I think 1 is the most important in terms of "what route should we go next", so let's chew on that first
- supporting handler style is maybe nice for existing middleware? (on the other hand I don't know who has custom middleware and not the grit to adapt it to an xform style - for bb support) - we should support the current way, for backwards compat - transducers are cool :) - middleware->transducer already works. It might be easy to adapt it a bit to support the nrepl.middleware descriptor keys. - Maybe there is a way to be able to handle both forms, so users can write xforms I go sleep 🙂
The current state of this is that I was thinking about what it would take to copy the cider nrepl code and write an inspect.clj.
I ran into the trouble that transport
in nrepl middleware has a different contract from our transformation paradigm.
Transport basically allows you to send and receive from within the middleware.
But our paradigm is a pure transformation stack, that decides to return (one or many, or filters) responses. It would also go into not only forking cider-nrepl but also nrepl which seems daunting.
I stopped until I have an idea for this.
I could try building an inspect.clj
without using any nrepl middleware utils etc. Might be straightforward.
nrepl.transport
(defprotocol Transport
"Defines the interface for a wire protocol implementation for use
with nREPL."
(recv [this] [this timeout]
"Reads and returns the next message received. Will block.
Should return nil the a message is not available after `timeout`
ms or if the underlying channel has been closed.")
(send [this msg] "Sends msg. Implementations should return the transport."))
A transport object is added to the message context that is passed to the middleware handler.
In principle a middleware can call recv
and as far as I understand wait for a message.
In practice this is mostly used to wrap a transformation for a handler. (Basically a map
or filter
in our scheme).
The idiom in middleware code seems to be to implement Transport
and modifying the send
while leaving recv
alone - I have not found any example for recv
.
Here is a representative example of imeplementing the protocol:
(defn- caught-transport
[{:keys [transport] :as msg} opts]
(reify Transport
(recv [_this]
(transport/recv transport))
(recv [_this timeout]
(transport/recv transport timeout))
(send [this {:keys [::throwable] :as resp}]
(let [{:keys [::caught-fn ::print?]} (-> (merge msg (bound-configuration) resp opts)
(select-keys configuration-keys))]
(when throwable
(caught-fn throwable))
(transport/send transport (cond-> (apply dissoc resp configuration-keys)
(and throwable print?)
(update ::print/keys (fnil conj []) ::throwable)
(not print?)
(dissoc ::throwable))))
this)))
cider-nrepl uses transport/send
to communicate with the client. with-safe-transport
. Is calling send
with the result of a handler fn.Thanks, this seems another incompatibility with the xform approach, or maybe not inherently?