Generics in Clojure
Clojure introduced protocols and multimethods as a way to achieve polymorphism and generic-like behavior. While Clojure doesn’t have built-in generics like some statically-typed languages, we can achieve similar functionality using these features.
Let’s start with an example similar to the SlicesIndex
function:
(defn index-of
"Returns the index of the first occurrence of v in coll, or -1 if not found."
[coll v]
(let [i (.indexOf coll v)]
(if (= i -1) -1 i)))
(println "index of zoo:" (index-of ["foo" "bar" "zoo"] "zoo"))
In Clojure, we don’t need to specify type parameters as it’s a dynamically-typed language. The index-of
function works with any collection that supports the .indexOf
method.
Now, let’s create a generic-like linked list:
(defprotocol IList
(push [this v])
(all-elements [this]))
(deftype List [^:volatile-mutable head]
IList
(push [this v]
(set! head (cons v head)))
(all-elements [this]
(reverse head)))
(defn create-list []
(List. nil))
(let [lst (create-list)]
(push lst 10)
(push lst 13)
(push lst 23)
(println "list:" (all-elements lst)))
In this example, we define a protocol IList
that specifies the methods our list should implement. The List
type implements this protocol. We use a protocol here to achieve a form of polymorphism that’s similar to generics in other languages.
The push
method adds an element to the front of the list, and all-elements
returns all elements in the list.
To use our list:
(defn -main []
(println "index of zoo:" (index-of ["foo" "bar" "zoo"] "zoo"))
(let [lst (create-list)]
(push lst 10)
(push lst 13)
(push lst 23)
(println "list:" (all-elements lst))))
To run the program, you would typically put this code in a file (e.g., generics.clj
) and run it using the Clojure command-line tool:
$ clj generics.clj
index of zoo: 2
list: (10 13 23)
In Clojure, we achieve generic-like behavior through protocols and polymorphism. While it’s not exactly the same as generics in statically-typed languages, it allows us to write flexible, reusable code that can work with different types.