Clojure - how to let the library users choose which printing function to use, to display data structures?

。_饼干妹妹 提交于 2019-12-24 22:00:59

问题


I'm writing a small debugging library and I would like to let users choose how to display data structures. I was imagining that users could require it in this kind of way:

(ns some-user-namespace
  (:require
    [clojure.pprint]
    [my.library :with-args {print-fn clojure.pprint/pprint}]))

Is something like this possible, and if not, how can I solve this problem?


回答1:


It's not possible to do it this way. If you really to offer this kind of setup, you could provide a configuration function to be called by the user after the import:

(ns some-namespace
  (:require [my.library]))

(my.library/print-with! clojure.pprint/pprint)

Ending function name with ! is an idiomatic way of indicating that it's causing some side effects.

In your library it could look like:

(ns my.library)

(def config (atom {:printer println}))

(defn print-with! [new-printer]
  (swap! config assoc :printer new-printer))

(defn my-lib-print [foo]
  ((:printer @config) foo))

EDIT: For a solution that does not require global, mutable state you can use dynamic bindings.

Lib:

(ns my.library)

(def ^:dynamic *printer* println)

(defn my-lib-print [foo]
  (*printer* foo))

Usage:

(binding [my.library/*printer* clojure.pprint/pprint]
  (my.library/my-lib-print {:hello "World"}))

These are the only two ways for some kind of external, contextual configuration I can think of. The only alternative is pure higher order function:

(defn my-lib-print [printer foo]
  (printer foo))


来源:https://stackoverflow.com/questions/24951894/clojure-how-to-let-the-library-users-choose-which-printing-function-to-use-to

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!