此问题与one I asked recently有关。
如果我将(fn [n] (fn [x] (apply * (repeat n x))))
重写为
(defn power [n] (fn [x] (apply * (repeat n x))))`
这样使用时效果很好
((power 2) 16)
我可以用另一种力量代替2,但我想为正方形,立方体等制作一个函数。最好的方法是什么?我一直在REPL中摆弄它,但到目前为止没有运气。
答案 0 :(得分:7)
使用宏来完全围绕他的问题,即“我有一个生成闭包的函数,我该如何给出这些闭包的名字?”简单的解决方案是:
(letfn [(power [n]
(fn [x]
(apply * (repeat n x))))]
(def square (power 2))
(def cube (power 3)))
如果你真的很讨厌重复def
和power
几次,那么只有这样才能让宏参与其中。但是,除非你将函数定义为至少十分之一的功能,否则你将花费在最简单的宏上的努力量将会被浪费,而与使用函数执行它的简单性相比。
答案 1 :(得分:1)
不确定这是否是您正在搜索的内容,但可能是宏模板。以下是我编写代码的方法:
(use 'clojure.template)
(do-template [name n]
(defn name [x] (apply * (repeat n x)))
square 2
cube 3)
user> (cube 3)
;=> 27
对于更复杂类型的类似任务,您可以编写一个包裹do-template
的宏来对其参数执行某些转换,例如:
(defmacro def-powers-of [& ns]
(let [->name #(->> % (str "power") symbol)]
`(do-template [~'name ~'n]
(defn ~'name [~'x] (apply * (repeat ~'n ~'x)))
~@(->> ns
(map #(vector (->name %) %))
flatten))))
(def-powers-of 2 3 4 5)
user> (power3 3)
;=> 27
user> (power5 3)
;=> 243
P.S。:如果你刚刚开始使用Clojure,那宏可能看起来很尴尬,不要因为它而放弃! ; - )