如何从闭包定义函数

发布于 2024-12-07 19:12:54 字数 414 浏览 0 评论 0原文

这个问题与我最近问过的问题相关。

如果我重写 (fn [n] (fn [x] (apply * (repeat nx)))) 因为

(defn power [n] (fn [x] (apply * (repeat n x))))`

它在这样使用时工作得很好,

((power 2) 16)

我可以用另一种幂代替 2,但是我'我想为平方、立方等创建一个函数。最好的方法是什么?我一直在 REPL 中摆弄它,但到目前为止还没有成功。

This question is related to one I asked recently.

If I rewrite (fn [n] (fn [x] (apply * (repeat n x)))) as

(defn power [n] (fn [x] (apply * (repeat n x))))`

it works just fine when used like this

((power 2) 16)

I can substitute 2 with another power, but I'd like to make a function just for squares, cubed, and so on. What is the best way to do that? I've been fiddling with it in the REPL, but no luck so far.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

顾铮苏瑾 2024-12-14 19:12:54

使用宏完全解决了他的问题,即“我有一个生成闭包的函数,我如何为这些闭包命名?”简单的解决方案是:

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

如果您真的讨厌多次重复 defpower,那么只有到那时才需要使用宏。但是,与使用函数执行此操作的简单性相比,除非您定义的函数至少达到十次方,否则您在即使是最简单的宏上花费的精力也会被浪费。

Using a macro for this goes entirely around his question, which was "I have a function that generates closures, how do I give those closures names?" The simple solution is:

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

If you really truly hate repeating def and power a few times, then and only then is it time to get macros involved. But the amount of effort you'll spend on even the simplest macro will be wasted unless you're defining functions up to at least the tenth power, compared to the simplicity of doing it with functions.

荒路情人 2024-12-14 19:12:54

不太确定这是否是您正在寻找的内容,但宏模板可能就是它。以下是我编写代码的方式:

(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

PS:该宏可能看起来很尴尬如果您刚刚开始使用 Clojure,请不要因此而放弃! ;-)

Not quite sure if this is what you're searching for, but macro templates might be it. Here's how I would write your code:

(use 'clojure.template)

(do-template [name n]
  (defn name [x] (apply * (repeat n x)))
  square 2
  cube   3)

user> (cube 3)
;=> 27

For more complex type of similar tasks, you could write a macro that wrap do-template to perform some transformation on its arguments, e.g.:

(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.: That macro might look awkward if you're just starting with Clojure though, don't give up because of it! ;-)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文