Having recently seen a presentation of Clojure Protocols, I was quite impressed by the clean way extensions to existing types can be done this way.
However, I was pretty sure to have already seen a similar way of doing this in some other language and after some time I found out it was Groovy Categories.
Compare this:
@Category(String) class StringCategory {
String lower() {
return this.toLowerCase()
}
}
use (StringCategory) {
println("TeSt".lower())
assert "test" == "TeSt".lower()
}
to the Clojure Protocol equivalent (taken from mikera’s answer below and tested in ideone.com)
(defprotocol Lowerable
(lower [x]))
(extend-protocol Lowerable
String
(lower [s]
(.toLowerCase s)))
(println (lower "HELLO"))
my question is:
- besides from performance differences (it is said that Clojure is highly optimized in this regard) – is there a semantic difference between the two approaches?
- besides the clumsy syntax, is there anything logically wrong with the Groovy approach?
Disclaimer: I am a complete Clojure newbie!
Here’s the rough equivalent Clojure code using protocols:
The key distinctions to note about Clojure protocols (which I believe make it distinctive from the Groovy categories version)
lowerto work on a Rope.loweris a proper first class function. So you can use it to build higher order abstractions (via higher order functions) that in turn will accept any arguments to which the Lowerable protocol has been extended.Clojure protocols are actually a fairly unique solution to the Expression Problem (linked video is pretty interesting). I think the closest equivalent to Clojure protocols in another language is actually Haskell type classes. Even then it’s a bit of a stretch since Haskell is statically typed and Clojure is dynamically typed….