如何从闭包定义函数

时间:2011-10-02 15:01:27

标签: clojure

此问题与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中摆弄它,但到目前为止没有运气。

2 个答案:

答案 0 :(得分:7)

使用宏来完全围绕他的问题,即“我有一个生成闭包的函数,我该如何给出这些闭包的名字?”简单的解决方案是:

(letfn [(power [n]
          (fn [x]
            (apply * (repeat n x))))]
  (def square (power 2))
  (def cube (power 3)))

如果你真的很讨厌重复defpower几次,那么只有这样才能让宏参与其中。但是,除非你将函数定义为至少十分之一的功能,否则你将花费在最简单的宏上的努力量将会被浪费,而与使用函数执行它的简单性相比。

答案 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,那宏可能看起来很尴尬,不要因为它而放弃! ; - )