Как определить функцию из замыкания - PullRequest
1 голос
/ 02 октября 2011

Этот вопрос относится к одному, который я недавно задавал .

Если переписать (fn [n] (fn [x] (apply * (repeat n x)))) как

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

работает нормально, если используется

((power 2) 16)

Я могу заменить 2 другой степенью, но я хотел бы сделать функцию только для квадратов, кубов и т. Д. Каков наилучший способ сделать это? Я возился с этим в REPL, но пока не повезло.

Ответы [ 2 ]

7 голосов
/ 03 октября 2011

Использование макроса для этого полностью связано с его вопросом: «У меня есть функция, которая генерирует замыкания, как мне дать имена этим замыканиям?» Простое решение:

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

Если вы действительно ненавидите повторять def и power несколько раз, тогда и только тогда пришло время задействовать макросы. Но количество усилий, которое вы потратите даже на самый простой макрос, будет потрачено впустую, если вы не определяете функции с точностью до десятой степени по сравнению с простотой выполнения этого с помощью функций.

1 голос
/ 02 октября 2011

Не совсем уверен, что это то, что вы ищете, но это могут быть шаблоны макросов.Вот как я написал бы ваш код:

(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, не сдавайтесь из-за этого!; -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...