beginners 2026-09-16

Protocols in Clojure On first looks like Java interfaces in Clojure language. Recalls old not so good memory of Java and object oriented design, so in the start for me feels wrong to use them in dynamical language What is you experience do you use them if yes for what, can you give me example ? Also Can we solve protocol cases with multimehods ?

protocols are nice because implementors don’t have to be source code. multimethods this is true, for java interfaces you need a compilation unit that implements the interface. Protocols can be quickly reified in a test namespace to do whatever you want. Want some kind of user service that throws an error on the third time it’s used reify it up.

πŸ‘ 2

Also, protocols can be declared to be implemented via metadata, so you can use any Clojure object that supports metadata, such as a function, for example. datafy and nav are good candidates for this, but also things like Component's Lifecycle protocol. So, that all feels a lot less "OO-y" and more just "extending behavior to new contexts".

Starts with a plain hash map. When you call start on that hash map, you get back a function that you can call to return the connection pool that was created, and you can call stop on that function to shutdown the connection pool.

@seancorfield thans good example

https://github.com/thi-ng/geom/blob/feature/no-org/src/thi/ng/geom/core.cljc one of the most interesting and powerful use cases for protocols I've seen is to implement a common set of geometric operations and implement them for different shape types. particularly for "number crunching" type code that computes geometric relationships, protocols offer a lot better performance than multimethods.

πŸ†’ 1
❀️ 1

What OO sometimes does wrong is making hierarchies: A square is a rect. And that makes for akward β€œdiamond” situations, for example, a rounded rect is a rect or is a circle (no to both or yes to both). A good protocol (or type class, or trait, or even Java interface) is about what something can do. For example in the link shared by @afoltzm, ICircumference says something about a shape without making a brittle hierachy.

Somewhat similar for the Clojure collections. We say that a map is associative, because this value supports associating keys to values. So a map could have implemented the Associative protocol (although, for historical reasons, no such protocol exists. I believe they are modeled as Java interfaces instead).

You shouldn't reach for protocols very often. It's not like in OOP where you start off by modeling a set of interfaces and classes and all that. At first you should always just start with plain data-structures like maps and plain functions in a namespace. Then if you need a function to behave differently for different input shapes, you can just use case/cond. Then if you want to be able to extend that function to work on a new input shape without having to change the function itself (by adding a new case/cond statement to it), you can reach for multi-methods. Then if you need the shape->impl dispatch for that function to be even faster than a cond/case or multi-method dispatch, and you're dispatching not on the shape but on the type of the input, you can switch to a protocol. And finally, if you also have more than one function that together should all behave differently for different input shapes, but like as a unit. So for some input shape, you have 2+ functions to all behave specially for that same input shape. Then you also reach for protocols for this, as it groups them together, which you can't do with multi-methods.

πŸ™‚ 1

@lennart.buit so it about modeling behavior not data structure I get it πŸ™‚

@didibus aha multimethod is dispath on the value vs protocol is dispatch on the type ... but first you start with basic map and see where it goes For examples If I am to design rate limiter and have to chose its algoritam (token bucket, leacky bucket slide window...) β€’ it can be simple if β€’ it can be condition β€’ if I want do decide on some input value or input calculation then it is multimethod β€’ if I want to decide on the inpt type then is protocol in this case when comes to the protocol as @lennart.buit said we re not doing here OOP and hierachies but polimorphism on behavior

That sounds like the Strategy design pattern, and we'd implement that by using a higher-order function, i.e., passing the strategy function into the rate limiter. The strategy function itself might be implemented as a plain function or a multimethod.

I wouldn't expect there to be a "type" here for a protocol to be based off?

(nearly all design patterns from the OOP world turn into higher-order functions in FP, as we separate data from functionality, so things become a lot more generic)

@ivangavlik963 protocols were a late addition to Clojure. Clojure was entirely capable before protocols, but protocols impose a lower run-time tax than multimethods. Even so, protocols still allow open extension (implement your protocol's method(s) for types that already exist) and avoid the OOP pitfall (implementation inheritance)

😁 1

@ivangavlik963 Ya, with the caveat Sean mentioned that you could also choose a design where you inject the chosen behavior function. But otherwise that's the deal. Multi-method can also dispatch on type as well as value, but protocol type dispatch will be faster. Multi-method can dispatch on type of all its arguments as well, not just first argument, where as protocol can only dispatch on type of first argument.

@seancorfield separate data from functionality that is what I also would like to understand better - but lets leave it for sepparate post thread

thanks you guys for your effort now I have much better understanding of why when to use it and how it is improvment compared to Java interfaces

Yep Clojure Protocols look a bit like interfaces and are somewhat class-ish. But (important difference with most OOP langs) not the entire language is build around this sort of construct or forces you build stuff only this way, you can chose the construct when you think it's helpful. IMHO they can fit when also plain OOP fits well, e.g. representing APIs, or infra/computing concepts such as libraries to interact with DBs (e.g. protocol/interface with methods like connect, commit, rollback, etc, and the specific implementations). But then (as always) it depends on context and team conventions. I agree with previous comments saying that you'd probably use them sparingly (and nothing wrong if you don't use them).

Every Clojure app I build is an Integrant system that composes a bunch of protocol implementations. It helps make explicit the boundaries in the system, and also what needs to be mocked in integration/functional tests. Their value is more in what they communicate than what they might enforce.

❀️ 1

> Their value is more in what they communicate than what they might enforce. πŸ’―

> How things happen, this is the actual implementation code, the work of doing the job. You strictly want to connect these things together using those polymorphism constructs. That's the most powerful thing. Yeah, you can use a switch statement. You could use pattern matching. But it's glomming all this stuff together. > From https://github.com/matthiasn/talk-transcripts/blob/master/Hickey_Rich/SimpleMadeEasy.md

@ivangavlik963 The key is to think in terms of the expression problem. Protocols solve it neatly, for conventional Java types. i.e. we can do OOP properly in Clojure, but not in Java. Example: A web UI testing mini-language I built around the so-called "page object" abstraction of web testing. I picked protocols over multimethods at the time, mainly because I was afraid of being tempted into making a maximal language... Performance was not a consideration, but restricting dispatch on a single type was a useful design constraint for me then. Today, I'd still use records to define page objects, but use multimethods to process them. Deck: see slide 17, "Learning Material", for resources I like, that explain protocols well, and slide 19, "Ideas to use Protocols / Records" https://github.com/adityaathalye/slideware/blob/master/designing_object_functional_system_IN-Clojure_2016.pdf Talk + demo: https://youtu.be/hwoLON80ZzA?si=b6pnGV1IUjyPryHp

@adityaathalye thanks

πŸ–– 1