Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Abstract functions or function interfaces in Clojure?

Tags:

clojure

In a number of occasions I have a collection of functions that I'd like to implement in different ways. The most obvious example of this would be to abstract from specific databases. In an object-oriented language you would use an interface for this:

interface DB {
  ResultSet query(String query);
  void persist(Object o);
  ...
}

In speudo code I would want to do something like this:

(ns dbbackend)

(abstractfn query [q])
(abstractfn persist! [o])

And then implementations for each database:

(ns dbbackend.mysql :implements dbbackend)
(defn query [q] ...)
(defn persist! [o] ...)

It is not entirely clear to me what the best practice is to do something similar in a functional language, specifically Clojure. Should I use multi-methods for this?

like image 864
Zef Hemel Avatar asked Jan 06 '10 07:01

Zef Hemel


2 Answers

Now that version 1.1 of Clojure has been released maybe it's time to take a look into the future.

Datatypes and protocols, which are currently only available in the new master branch on github , might be exactly what you are looking for.

(defprotocol DB
  (query   [backend query])
  (persist [backend object]))

(deftype MySQLBackend []
  DB
  (query   [query] ...)
  (persist [object] ...))
like image 128
Jonas Avatar answered Nov 20 '22 09:11

Jonas


For pre-protocol Clojure versions:

The interface:

(ns dbbackend)

(defmulti query
  {:arglists '([c q])}
  suitable-dispatch-fn)

(defmulti persist!
  {:arglists '([c o])}
  suitable-dispatch-fn)

The implementation:

(ns dbbackend.mysql
  (:requires dbbackend))

(defmethod query com.mysql.jdbc.Connection
  [c q]
  ...)

(defmethod persist! com.mysql.jdbc.Connection
  [c o]
  ...)

The usage:

(ns user
  (:require dbbackend dbbackend.mysql))

(def mysql-connection (connect-to-mysql))
(query mysql-connection some-query)

You can find a real-world example of this approach under the hood of ClojureQL.

like image 20
kotarak Avatar answered Nov 20 '22 08:11

kotarak