2011-10-02 40 views
1

此问题与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

我没有得到你的问题。你想创建功能的集合:正方形,立方体等? –

+0

是的。我宁愿采用(power 2)语法,并用power2,power3(立方体)替换它,等等。当然,有一个数学库,在生产代码中,我不会这样做,但我试图将原始函数映射为它将如何接收它的参数,并且在REPL中试用这个函数非常有帮助。 – octopusgrabbus

回答

7

为此,使用宏完全围绕他的问题,即“我有一个生成闭包的函数,我如何给这些闭包名称?”简单的解决办法是:

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

如果你真的真的恨重复defpower了几下,然后才把是时候涉足宏。但是,即使是最简单的宏,您花费的精力也将被浪费,除非您定义的功能至少达到十分之一的功率,而功能却很简单。

+0

是的,但他的问题似乎错误地表达出来,我不确定这很简单。 “等等”部分告诉我他正在寻找的不仅仅是他实际要求的东西?我向你提出了严格的要求。 –

+0

(def square(power 2))就是我在找的东西,但有一个宏观答案也很有帮助。就我个人而言,我会使用(电源2),但想知道如何缩短它。 – octopusgrabbus

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))) 
     [email protected](->> ns 
       (map #(vector (->name %) %)) 
       flatten)))) 

(def-powers-of 2 3 4 5) 

user> (power3 3) 
;=> 27 

user> (power5 3) 
;=> 243 

PS:如果你刚刚开始使用Clojure,那么这个宏可能看起来很尴尬,不要因为它而放弃! ;-)

+0

谢谢。这是一个很好的答案。很多我学习Clojure的问题让我的眼睛笼罩在语法上。我用越来越少的小屁股来制作不一定会用的东西,我就越了解东西。 – octopusgrabbus