How do you write library wrappers?

Maybe I’m doing something wrong… or maybe what I’m trying to do is maybe just “bad Clojure”

So I often have little “utility” functions. Say for instance I have a code snippet that makes a map out of the CSV vector-of-vectors output by clojure.data.csv/read-csv.

What I’d like to do is wrap and extend clojure.data.csv (and maybe rename some of its functions) - but I’m fighting the ns macro. I can write my own my-csv library. It can require or use the functionality in clojure.data.csv and write some csvvec-2-map function. But I don’t know how to forward all the symbols.

especially if I want to rename some function… I’d like to require one library and not have to require both my-csv and clojure.data.csv and then track where is what.

I also have a set of libraries that I use in virtually all my projects. I kinda don’t want to keep copy and paste’ing a bloated ns declaration across every project and I’d like to consolidate everything into one wrapper ns that I can then (:require all-my-standard-libs)

But when I try this, I notice the what’s :rename’ed or :use’d inside a ns isn’t forwarded to the library user - nor do I know a mechanism to do it

How are people handling this…? Especially on large projects, I imagine you have huge ns decls that are all virtually the same across all the project’s ns’s

How do you write library wrappers?

We don’t. :slight_smile:

Consider e.g. clojure.zip and clojure.data.zip. The latter just adds a few functions to help you work with the functionality from the former. It’s not a wrapper-replacement, it’s a helper.

I use import-vars for this kind of plumbing. I have seen projects that have a common facing api that want to pass through references to the dependent ns or coalesce stuff in a common api (like tech.v3.dataset.api using a similar mechanism via the export-symbols macro).

So one strategy might be to write something like:

(ns mycsv 
   (:require [clojure.data.csv] 
             [potemkin :as pot]))

(pot/import-vars 
   [clojure.data.csv
   read-csv
   write-csv])

(defn my-stuff [arg] 
  ;;use your imagination
  )

In another ns:

(ns blah 
   (:require [mycsv :as csv]))

;;public vars from mycsv should be exposed, including imports:

;;csv/my-stuff 
;;csv/read-csv   - should actually map to clojure.data.csv/read-csv e.g. if you look at the doc string
;;csv/write-csv  - same
3 Likes

haha, clever lib name. That seems to do most of what I’d want except renaming. Thank you for pointing me in the right direction :slight_smile: (and Injest last time)

For renaming I can just write thing wrappers I guess

the renaming part can be done with intern. see the copy single method. It works with both functions and macros:

1 Like

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.