4

I have a namespace that exposes common data-related functions (get-images, insert-user). I then have two database backends that have those same functions and implement them differently. They implement the interface as it were. Each backend is contained within a namespace.

I can't seem to be able to find a good solution on how to accomplish this.

I tried dynamically loading the ns but no luck. Once you do (:require [abc :as x]), the x isn't a real value.

I tried using defprotocol and deftype but that's all kinds of weird because the functions in the deftype need to be imported, too and that messes everything up for me.

Is there some idiomatic solution to this?

1 Answer 1

9

I don't see why protocols are not sufficient?

In ns data.api:

(ns data.api)
(defprotocol DB
  (get-images [this]) 
  (insert-user [this]))

In ns data.impl1:

(ns data.impl1
  (:require [data.api :refer :all]))

(defrecord Database1 [connection-params]
  DB
  (get-images [_] ...)
  (insert-user [_] ...))

Same thing in ns data.impl2.

Then when you go to use a particular db, just create the correct record:

(ns data.user
  (:require [data.api :refer :all])
            [data.impl1 :refer (->Database1)])

(defn use-db []
  (let [db1 (->Database1 {})]
    (get-images db1)))
Sign up to request clarification or add additional context in comments.

4 Comments

FWIW, it seems like the preferred way to use records/types from another namespace is by importing them, i.e. (:import [data.impl1 Database1]) inside of the (ns data.user ...) groups.google.com/forum/#!topic/clojure/ILPz4QOEod8
@DaveYarwood: Is it? That thread doesn't really suggest that to me. It's just one guy who's doing it that way and is wondering why that approach requires underscores instead of dashes.
That thread likely predates Clojure 1.4. As of 1.4, defrecord causes the creation of a positional (eg ->Database1) and map (eg map->Database1) constructors, which are the preferred way to construct new records. When using those there is no need to import the underlying record class, just refer in the constructor function itself.
You're right, I was just going about it the wrong way somehow. This is perfect. Thanks

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.