2024 年 Clojure 调查问卷 中分享您的想法!

欢迎!请参阅 关于 页面以了解更多关于此工作的信息。

0 投票
Clojure

Python 有一种名为装饰器的数据结构,允许在不修改资源结构的情况下改变其功能。如果您需要在运行时更改行为,这非常有帮助。

一些参考资料
https://www.pythonlang.cn/dev/peps/pep-0318/
https://www.datacamp.com/community/tutorials/decorators-python

我进行了一些搜索,没有看到 Clojure 中类似的数据结构。有没有其他可用资源可以达到相同的效果?

谢谢!

2 答案

+2 投票

装饰器不是一种数据结构。它是一种不必要的语法糖,只是为了使某些代码更容易阅读而实现的,仅此而已。
而且您无法使用它来改变运行时中的某些内容,除非您依赖于一些全局变量或引入其他引用的不透明性。

话虽如此,任何将函数视为一等公民的语言都有一种方法可以以相同的方式实现相同的功能,也许没有特殊糖衣。

您链接的教程给出了以下示例

@split_string
@uppercase_decorator
def say_hi():
    return 'hello there'

在 Clojure 中实现它的最相似方式可能是这样的

(def say-hi (comp
             split-string 
             uppercase-decorator
             (fn [] "hello there")))

尽管我只想把它全部包装在一个函数中,这在Clojure中要简单得多,因为Clojure中没有任何地方会出现像Python那样的 return 语句

(defn say-hi []
  (-> "hello there"
    uppercase-decorator
    split-string))
0 投票

我完全同意Eugene的看法。为了以防万一,我想补充一下,您还可以编写一个可以模拟预期行为的宏。

(defmacro with-decorators
  [decorators fname & body]
  `(def ~fname (comp ~@(reverse decorators) (fn ~@body))))

(require '[clojure.string :as s])

(with-decorators
  ;; decorators
  [s/upper-case #(s/split % #"\s+")]
  ;; function definition as in `defn`
  say-hi []
  "hello there")

(say-hi)
;; => ["HELLO" "THERE"]
...