gpt4 book ai didi

clojure - Clojure 是否有一种高效、惯用的装饰器方法?

转载 作者:行者123 更新时间:2023-12-02 11:02:59 24 4
gpt4 key购买 nike

在 Clojure(script) 中,您可以使用 deftypedefrecord 定义编程结构。我们希望我们的每个构造都有一个特定的、明确定义的目的。我们选择分离职责,而不是将任何一种构造发展成一个单一的、功能齐全的东西。装饰器(例如包装其他数据结构的数据结构)对此很有用。

例如,您有一个记录器构造。您可以使用装饰器添加时间戳作为一项功能。您稍后添加警报支持人员蜂鸣器作为另一个装饰器。理论上,我们可以通过这种方式对任意数量的功能进行分层。我们的配置文件清楚地确定了包含哪些功能。

如果我们的记录器实现了 3 种方法的日志记录协议(protocol),并且每个装饰器只增强了一个,那么您仍然需要在每个装饰器上实现其他两个方法来维护契约 api。这些不添加任何内容的实现只是将消息沿着链传递。这是尴尬的一点。

构造的 api 越丰富,问题就越严重。考虑一个实现一些协议(protocol)的构造以及装饰处理 12 个左右方法的东西所需的工作。

您是否发现了可以克服此问题的机制、宏或技术?

最佳答案

一种选择是使用 extend 来合并默认委托(delegate)函数和重写实现的组合。

例如,使用如下记录器协议(protocol):

(defprotocol Logger
(info [logger s])
(warn [logger s])
(debug [logger s]))

(def println-logger
(reify Logger
(info [_ s]
(println "Info:" s))
(warn [_ s]
(println "Warn:" s))
(debug [_ s]
(println "Debug:" s))))

您可以编写一个函数来创建装饰器实现,如下所示:

(defn decorate-fn
"Creates a decorator function
given the implementation accessor and the called function."
[impl f]
(fn [decorator & args]
(apply f (impl decorator) args)))

(defn gen-decorators
"Creates a map of decorator functions."
[impl fs]
(into {} (for [[k f] fs]
[k (decorate-fn impl f)])))

(defn decorate-logger
"Creates a logger decorator with functions
passing through to the implementation by default."
[impl overrides]
(merge (gen-decorators impl
{:info info
:warn warn
:debug debug})
overrides))

然后用它来轻松创建装饰器:

(defrecord CapslockWarningLogger [impl])

(extend CapslockWarningLogger
Logger
(decorate-logger :impl
{:warn (fn [{:keys [impl]} s]
(warn impl (clojure.string/upper-case s)))}))

(defrecord SelectiveDebugLogger [ignored impl])

(extend SelectiveDebugLogger
Logger
(decorate-logger :impl
{:debug (fn [{:keys [impl ignored]} s]
(when-not (ignored s)
(debug impl s)))}))

(def logger
(->SelectiveDebugLogger #{"ignored"}
(->CapslockWarningLogger
println-logger)))

(info logger "something")
; Info: something
; => nil

(warn logger "something else")
; Warn: SOMETHING ELSE
; => nil

(debug logger "ignored")
; => nil

关于clojure - Clojure 是否有一种高效、惯用的装饰器方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44952525/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com