Я могу сделать clojure макрос, который позволит мне получать список всех функций, созданных макросом?

Я хотел бы иметь макрос, который я назову нечто определения. Нечто определения создаст функцию и затем добавит эту функцию к набору.

Таким образом, я мог звонить

(def-foo bar ...)

(def-foo baz ...)

И затем был бы некоторый набор, например, все-foos, который я мог назвать:

all-foos
=> #{bar, baz}

По существу я просто стараюсь не повторять меня. Я мог, конечно, определить функции нормальным способом, (defn панель...) и затем записать набор вручную.

Лучшая альтернатива, и более простой, чем макро-идея, должна была бы сделать:

(def foos #{(defn bar ...)    (defn baz ...)} )

Но мне все еще любопытно относительно того, существует ли хороший путь к макро-идее работать.

5
задан Rob Lachlan 1 June 2010 в 22:04
поделиться

2 ответа

Вы хотите получить набор, в котором есть имена функций (т.е. набор символов), или набор, содержащий переменные (которые разрешаются в функции)? Если вам нужно первое, вы можете добавить символы к атому в макросе во время компиляции, как в версии Грега Хармана.

Если вы хотите последнее, ваш макрос должен расшириться до кода, который выполняет обмен атомами после определения функции. Помните, что макросы выполняются во время компиляции, а результат с расширенным макросом выполняется во время выполнения; сама функция недоступна до времени выполнения.

(def all-foos (atom #{}))

(defmacro def-foo [x]
  `(let [var# (defn ~x [] (println "I am" '~x))]
     (swap! all-foos conj var#)))

Если вы хотите иметь возможность вызывать функции, например, из этого набора, вам необходимо использовать последнюю версию.

user> (def-foo foo)
#{#'user/foo}
user> (def-foo bar)
#{#'user/foo #'user/bar}
user> ((first @all-foos))
I am foo
nil
5
ответ дан 13 December 2019 в 22:02
поделиться

Попросите макрос добавить имя новой функции в ваш набор перед созданием функции, например:

(def *foos* (atom (hash-set)))

(defmacro def-foo [name]
  (swap! *foos* conj name)
  `(defn ~name
     []
     (println "This is a foo!")))

Результат:

user=> (def-foo bar)
#'user/bar
user=> (def-foo baz)
#'user/baz
user=> (bar)
This is a foo!
nil
user=> (baz)
This is a foo!
nil
user=> *foos*
#<Atom@186b11c: #{baz bar}>
5
ответ дан 13 December 2019 в 22:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: