Как мне написать этот макрос в clojure?
У меня есть эта функция:
(defn handler [request]
(case (request :uri)
"/" (home request)
"/good" (good request)
"/evil" (evil request)
"/neutral" (neutral request)
(status-response 404 (str "<h1>404 Not Found: " (:uri request) "</h1>" ))))
но я продолжаю изменять список страниц, которые разрешают к функциям с тем же именем, и я хотел бы иметь возможность написать:
(def-handler, добро, зло, нейтраль)
вместо:
Но я застрял. Мой лучший снимок выглядит так:
(defmacro def-handler [& addresses]
`(defn handler [request#]
(case (request# :uri)
~@(mapcat (fn[x] [(str "/" x) (list x 'request)]) addresses)
"/" (home request#)
(status-response 404 (str "<h1>404 Not Found: " (:uri request#) "</h1>" )))))
Но это не совсем работает, потому что запрос в сгенерированных вызовах не является gensym, и я не знаю, как получить gensym там.
Это выглядело многообещающе, пока я не заметил, что это произвело новый генсим:
(defmacro def-handler [& addresses]
`(defn handler [request#]
(case (request# :uri)
~@(mapcat (fn[x] [(str "/" x) `( ~x request#)]) addresses)
"/" (home request#)
(status-response 404 (str "<h1>404 Not Found: " (:uri request#) "</h1>" )))))
2 ответа
Я думаю, что вы можете избежать здесь вообще. Я не понимаю, как можно "загрязнить" окружающую среду, не используя gensym. Пример без Генсым:
(defmacro def-handler [& addresses]
`(defn handler [~'request]
(case (~'request :uri)
~@(mapcat (fn[x] [(str "/" x) (list x 'request)]) addresses)
"/" (home ~'request)
(status-response 404 (str "<h1>404 Not Found: " (:uri ~'request) "</h1>" )))))
Проблема с вашим макрокодом состоит в том, что динамический символ, который является частью квазицитирования, не может использоваться вне заключенной в кавычки части, т. Е. В коде разделения / удаления кавычек. Однако возможен другой способ, то есть вы делаете gensym в части выполнения макроса и используете ее внутри части квазицитирования, как показано ниже:
(defmacro def-handler [& addresses]
(let [request (gensym)]
`(defn handler [~request]
(case (~request :uri)
~@(mapcat (ƒ [x] [(str "/" x) (list x request)]) addresses)
"/" (home ~request)
(status-response 404 (str "<h1>404 Not Found: " (:uri ~request) "</h1>"))))))