我读过那些数据>功能>宏
假设您想以后缀方式评估代码。
哪种方法会更好?
;; 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"
谢谢!
答案 0 :(得分:1)
如果您对代码中的任何类型的数据需要不同的评估行为,那么您最好选择,因为它们可以在编译时将未评估的数据转换为您想要评估的代码。
Clojure有一个编程宏系统,允许编译器通过用户代码进行扩展。宏可用于定义句法结构,这些结构需要原语或其他语言的内置支持。 (http://clojure.org/macros)
您提供的示例明确具有该要求(“以后缀方式评估代码”),这就是宏是正确选择的原因。
答案 1 :(得分:0)
一般来说:
然而,宏使用它们;宏在遇到它们时会扩展,因此您将在结果字节代码中内联一个或多个代码块。它们是封装高阶DSL术语的理想选择。
另一方面,函数非常适合重用,您可以在本地化函数的纯度,并且可以从多个其他函数调用它,而不会增加代码占用空间。它们非常适合本地化或全球使用。
REPL行为考虑:单个函数更容易返工,而不必担心完全评估整个源文件以确保所有宏引用扩展都得到更新。
希望这有帮助
答案 2 :(得分:0)
简单的规则是最好的:如果可以的话,使用一个函数,如果必须的话,使用宏。
答案 3 :(得分:0)
你的宏比你的功能更好:宏比使用eval
的函数更好。
但是,该功能无需使用eval
。你可以写它
(defn reverse-fn [data]
(apply (last data) (butlast data)))
然后,例如,和以前一样,
(reverse-fn [3 inc])
=> 4
在相关主题上,您可能会发现this explanation传感器很有趣。
编辑:
请注意,函数是文字,在函数评估自身的意义上:
((eval +) 1 1)
=> 2