请在 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 中没有任何地方可以出现的 return 语句,就像 Python 中有那样。

(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"]
...