Подтвердить что ты не робот

Как определить функцию внутри функции в Clojure и ссылаться на эту функцию?

Я написал функцию для вычисления симметричной разности двух множеств (одна из проблем на сайте 4clojure). Функция прошла модульные тесты, но не настолько чиста, как хотелось бы, учитывая, что у меня есть дублированный код.

(fn [x y] (set (concat 
  (keep-indexed #(if (nil? (get y %2)) %2) x)
  (keep-indexed #(if (nil? (get x %2)) %2) y))))

Очевидно, я предпочел бы что-то вроде:

(fn [x y] (set (concat (diff x y) (diff y x))))

Если функция diff определена и указана как "встроенная", но я не знаю, как это сделать в одном блоке fn.

4b9b3361

Ответ 1

Используйте let или letfn:

(fn [x y]
  (let [diff (... function body here ...)]
   (set
    (concat (diff x y) (diff y x)))))

Ответ 2

Одна из функций, которая делает Clojure a lisp (и вообще функциональный язык) в том, что функции являются первоклассными вещами в Clojure, в частности, это объекты. Когда вы создаете функцию с (defn name [arg] ...), если она создает функцию, а затем хранит ее в var, чтобы вы могли ее найти позже из любой точки вашей программы. это очень похоже на это:

(def name (fn [arg] ...))

теперь имя содержит функцию, которая широко доступна. Функции не должны храниться в vars, особенно если они необходимы только в вашей функции. В этом случае имеет смысл связывать функцию с локальным именем, как с ответом Мэтта Фенвика.

(let [name (fn [agr] ...)] ...)

макрос letfn делает это более элегантным. Важная часть состоит в том, чтобы понять, что функции - это объекты, которые хранятся в вещах, и вы можете выбрать контейнер, который соответствует вашим потребностям.