Fork me on GitHub
Ben Sless09:11:51

@seancorfield I remember some time ago we talked about the best way to mix components which we would want to implement protocols without a lot of boilerplate. My idea was to work with a component which still satisfied some framework protocols (like reitit's router) without change to the semantics. Came up with this, what do you think?


Should the second opts in line 17 be opts+specs? Otherwise that argument doesn't seem to be used?

Ben Sless17:11:59

Oh, right, I renamed the macro argument but forgot to update the binding


My personal feeling is that this is too much "magic" and it makes it very hard to just look at code and figure out what it actually does. I mean, how often do you really need a record to implement an arbitrary list of protocols -- and what are those implementations actually doing in this case?


OK, so macroexpand-1 seems to indicate this is just adding delegation of those protocols via the first field of the record -- but I don't understand why. What's the motivation for this (the discussion was some time ago)?


Also, if we're talking about Component, we're tending to implement Lifecycle via metadata a lot these days at work -- not records.


(although, unfortunately, IKVReduce doesn't support extension via metadata)

Ben Sless17:11:50

It's a balancing act between readability, convenience and "magic"

Ben Sless17:11:09

Let's say I want to bring in something like a malli registry or reitit router as a component

Ben Sless17:11:41

I can extend them via metadata, or I can just stick them as a "state" in a component and delegate their methods to them

Ben Sless17:11:58

Then the components appear very "vanilla"

Ben Sless17:11:43

They just have a list of "here are all the protocols (and interfaces?) I delegate to"

Ben Sless17:11:34

When I settle on how I want to do interfaces, too, I get a convenient way of delegating over java objects, too, which I can't extend via metadata

Ben Sless17:11:56

But take next.jdbc as another example, I can just specify a list of protocols on a record and it can "automagically" participate in them

Ben Sless17:11:29

no boilerplate, no wrapping, and no difference in semantics


What next.jdbc protocols would you want to delegate to? That's not a compelling argument to me. next.jdbc.connection/component already exists for making a Component that wraps a pooled datasource. What other things would you want to do?


This is just not a problem I've run into, so maybe it's specific to a couple of the libraries you're using that sort of expect you to implement a bunch of protocols with boilerplate?

Ben Sless17:11:32

I can give several examples • with next.jdbc I might not want to use the component wrapper, just due to preference •

Ben Sless17:11:07

The router example - depends on handlers. Handlers might be stateful (they might call a db)