Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

A record can implement protocols. However, each time I think of a new function that I would like the record to implement, I have to add it to an existing protocol or create a new protocol. How do I get around this? Ideally, I'd just like to associate a function to a record without having to define a protocol.

share|improve this question

Then just write a function that takes an instance of that record as an argument.

defrecord doesn't "implement" a protocol, in the sense that class in a Java-like OO language implements an interface. What it does is define a datatype, and give you some syntactic sugar to implement a protocol that operates on that datatype. There's a pretty great overview of just what sort of problem protocols are meant to solve here -

share|improve this answer

Excellent question. Here's an answer based on a similar one I gave on StackOverflow.

As usual, there's a beautiful way to do things in Clojure - here's how to implement your own simple dynamic OO system (including inheritance, polymorphism and encapsulation) in 10 lines of Clojure.

The idea: You can put functions inside normals Clojure maps or records if you want, creating an OO-like structure. You can then use this in a "prototype" style.

; define a prototype instance to serve as your "class"
; use this to define your methods, plus any default values
(def person-class
    (fn [this] (str (:first-name this) " " (:last-name this)))})

; define an instance by merging member variables into the class
(def john 
  (merge person-class 
    {:first-name "John" :last-name "Smith"}))

; macro for calling a method - don't really need it but makes code cleaner
(defmacro call [this method & xs]
  `(let [this# ~this] ((~method this#) this# ~@xs)))

; call the "method"
(call john :get-full-name)
=> "John Smith"

; added bonus - inheritance for free!
(def mary (merge john {:first-name "Mary"}))
(call mary :get-full-name)
=> "Mary Smith"
share|improve this answer
hmm just realised I've posted the same answer to the same poster on both StackOverflow and Programmers..... ah well, guess that both sites have audiences that would be interested! – mikera Feb 17 '11 at 11:19
See also… for an in depth discussion of the topic including the desugared version of the call macro syntax from mikera's answer. – John Nov 30 '13 at 11:46

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.