Clojure 在这个例子中避免使用宏是好的吗?
我读到数据>函数>宏 假设您希望以后缀方式计算代码 哪种方法更好Clojure 在这个例子中避免使用宏是好的吗?,clojure,Clojure,我读到数据>函数>宏 假设您希望以后缀方式计算代码 哪种方法更好 ;; Macro (defmacro reverse-fn [expression] (conj (butlast expression) (last expression))) (reverse-fn ("hello world" println)) ; => "hello world" ;; Function and data (def data ["hello world" println]) (def
;; Macro
(defmacro reverse-fn [expression]
(conj (butlast expression) (last expression)))
(reverse-fn ("hello world" println))
; => "hello world"
;; Function and data
(def data ["hello world" println])
(defn reverse-fn [data]
(apply (eval (last data)) (butlast data)))
(reverse-fn ["hello world" println])
; => "hello world"
谢谢 一般来说:
但是宏有它们的用途;宏在遇到宏时会展开,因此在生成的字节码中将内联一个或多个代码块。它们非常适合封装高阶DSL术语
另一方面,函数对于重用来说是非常好的,因为您可以本地化函数的纯度,并且可以从多个其他函数调用函数,而不会增加代码占用。它们非常适合本地或全球使用
REPL行为考虑:单个函数更易于返工,而无需担心完全评估整个源文件以确保更新所有宏引用扩展
希望这有帮助简单的规则是最好的:如果可以使用函数,如果必须使用宏。你的宏比你的函数好:宏比使用
eval
的函数好
但是,该函数不需要使用eval
。你可以写
(defn reverse-fn [data]
(apply (last data) (butlast data)))
然后比如说像以前一样,
(reverse-fn [3 inc])
=> 4
在一个相关的话题上,你可能会发现一些有趣的问题
编辑: 请注意,函数是文本,从函数自身求值的意义上讲:
((eval +) 1 1)
=> 2
如果对代码中的任何类型的数据要求不同的求值行为,宏是最佳选择,因为它们可以在编译时将未求值的数据转换为希望求值的代码 Clojure有一个编程宏系统,允许编译器通过用户代码进行扩展。宏可用于定义需要原语或其他语言内置支持的语法结构。() 您提供的示例明确地说明了这一要求(“以后缀方式评估代码”),这就是为什么宏是正确的选择