This is more me fooling around then anything serious. I was wondering if there’d be a way to implement simple objects using functions, but without closing over mutable data.
That said, there are some minor differences between objects and protocols/records. One difference is that the object encapsulates the data strongly.
If you look at my code, it’s not possible for anyone else to mess with the data fields through any other means but the object’s methods.
In my case, since I’m using immutable data it doesn’t really matter. But if they were mutable it would. Strong encapsulation would give you some guarantees that you can trust no one else will mutate your data under your feet.
Another one is that the behavior and the data are tightly coupled together with objects. So for example if you want to modify the data, it’s much more obvious what is the total set of methods over it which you need to refactor accordingly.
On that same line of thought, if you wanted auto-complete for example, because the relationship between the data and it’s set of methods is so strong, it is very easy to list out for any object all the possible methods. For example in my code, one can just call keys
on the object and you get the list of possible operations. So it be trivial to add auto-complete to my =>
macro in some editor for example.
None of those are killer features, I’m in no way advocating for OOP , just saying there are some minor differences when you start to go deep into the details.
But yes, for real Clojure, I’d probably not even use protocols I’d just go:
(defn make-counter
[]
0)
(defn inc [counter]
(inc counter))
(defn double [counter]
(* 2 counter))
(-> counter inc inc double)
Since I’m not making use of polymorphism, protocols give you no additional benefit then just plain functions over a simple data-structure as I just wrote.