I am designing a library to wrap an API with Clojure. The API requires user credentials to authenticate user related calls.

My first approach was to have functions that do each task the API can do:

(defn send-email
  [credentials email]
  (call-api credentials :email email))

(defn send-message
  [credentials message]
  (call-api credentials :say message))

However, I noticed that most of the functions have the same argument, credentials. Hence, I thought of another way to approach this. How about returning functions partialed with the credentials after you login:

(defn authenticate
    [username password]
    (let [credentials (api-auth username password)]
      {:credentials credentials
        :send-email (partial send-email credentials)
        :send-message (partial send-message credentials)})

This makes it much more convenient, the user of this library does not need to add the credentials on every call.

But wait, this looks a lot like what you would do in object-oriented programming. You pass something into a function (the initializer) and you get functions (from an object) that are tailored to what you passed in.

The above could have been written as this in Java:

public class Api {
    private String credentials;
    Api(String username, String password) {
        this.credentials = Utils.api_auth(username, password);

    void send_email(String email) {
        Utils.call_api(this.credentials, Utils.EMAIL, email);

    void send_message(String message) {
        Utils.call_api(this.credentials, Utils.SAY, message);

As Clojure is a functional programming language, I want to avoid object-oriented programming but it feels as though the whole task was meant for object-oriented programming languages.

How should I design for such an API? Which approach should I choose, or is there something I am not thinking of in my object-oriented mind?

UPDATE I thought of a third way: bindings:

(def ^:dynamic *credentials*)

(defn send-email
  (call-api *credentials* :email email))

(defn send-message
  (call-api *credentials* :say message))
; Usage
(binding [*credentials* (api-auth username password)]
  (send-email "hello")
  (send-message "hello"))

However, the problem with this is that it is very easy to create erroneous code—just don't bind anything at the start. This is different from implementations of dynamic vars I have seen (pprint), where there is a default binding.

  • Wrap it in a protocol if you want to feel more Clojurey.
    – kdgregory
    Commented Aug 8, 2017 at 0:08
  • @kdgregory according to the linked page, protocols are meant for abstractions. That means that it would be useful if I had more than one type of credentials... but I don't. Commented Aug 11, 2017 at 12:35
  • 1
    @MoonCheesez "this looks a lot like what you would do in object-oriented programming" So what? Commented Dec 9, 2017 at 17:38
  • 1
    @MoonCheesez Your clojure code is pure, isn't it? Commented Dec 11, 2017 at 8:02
  • 1
    Just FTR: (1) Yes, "objects" are families of partially-applied functions, usually namespaced under that object; (2) No, the partially-applied state is not required to be mutable. (3) Objects are not a problem; uncontrolled mutable state and uncontrolled effects are. You can have objects that play nice both with state (e.g. immurtable) and with effects (e.g. in a monadic way).
    – 9000
    Commented Jan 29, 2020 at 17:20

2 Answers 2


OO requires objects have mutable attributes

No, OO requires objects have attributes. There is a lot of OO code that uses objects with mutable attributes, and also a lot of OO code that uses objects with only immutable attributes.

Take a look at Java's String class, all the operations give you new Strings, rather than mutating the content of this.


Not sure if it is "functional" enough for you but you could replace call-api with call-auth-api and in that have it obtain credentials, possibly from a duration limited store, and supply them as one of the inputs to the actual call-api.

  • I think implementing a duration limited store can increase the complexity greatly as managing the store, especially expiring the store, will require a constant checking. Aside from that, pulling data from an external source in a function is not really functional... Commented Aug 11, 2017 at 12:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.