TL; DR:以下是图书馆的好模式吗?
(def ^{:dynamic true} *var*)
(defn my-fn [{:keys [var]}]
(do-smth (or var *var*)))
-
说我想写一个情绪分析库。
get-sentiment
fn中接受可选情绪标签但是提供默认标签作为动态变量是不是很好?
(def ^:dynamic *sentiment-level-labels*
["Very Negative" "Negative" "Neutral" "Positive" "Very Positive"])
;;...
(defn get-sentiment-scores
"Takes text and gives back a 0 to 4 sentiment score for each sentences."
[text]
;;...)
(defn get-sentiment
"Gives back a sentiment map with sentences scores,
average score, rounded score and labeled score.
Can accepts custom sentiment level labels under :labels opt."
[text & {:keys [labels]}]
(let [scores (get-sentiment-scores text)
average-score (get-average scores)
rounded-score (Math/round average-score)
label (get (or labels *sentiment-level-labels*) rounded-score)]
{:scores scores
:average-score average-score
:rounded-score rounded-score
:label label}))
Clojure图书馆编码标准官方页面说:
如果您提供隐式传递参数的接口 动态绑定(例如,sql中的db),也提供相同的接口 但是显式传递了参数。
https://dev.clojure.org/display/community/Library+Coding+Standards
在我的例子中,我只提供了一个接口但是带有opt参数。
这可以吗?有没有更好的方法来处理这个?
谢谢!
答案 0 :(得分:3)
动态变量已满或存在陷阱。他们将您的API代码推向隐式环境耦合,并且经常强制您的调用代码添加许多(binding ...)
子句,这首先使用动态变量来破坏简洁的目的。如果控制从一个线程传递到另一个线程,它们也会导致棘手的边缘情况。
在您的情况下,我建议您只需在params
地图参数中传递标签:
(def default-sentiment-level-labels
["Very Negative" "Negative" "Neutral" "Positive" "Very Positive"])
(defn get-sentiment
"Gives back a sentiment map with sentences scores,
average score, rounded score and labeled score.
Can accepts custom sentiment level labels under :labels opt."
[text {:as params, :keys [labels] :or {labels default-sentiment-labels}}]
...))
请注意,地图的使用可能很有趣,因为地图对中介不透明:您可以让算法的各种组件仅从params
地图中读取与其相关的键。