2015-03-06 8 views
3

Я создал новый проект Compojure Leiningen, используя lein new compojure test. Веб-сервер работает под управлением lein repl, а затемОбновление динамического обработчика в Clojure Ring/Compojure REPL

user=> (use 'ring.adapter.jetty) 
user=> (run-jetty test.handler/app {:port 3000}) 

Маршруты и описание обработчика приложения тривиальна:

(defroutes app-routes 
    (GET "/*.do" [] "Dynamic page") 
    (route/not-found "Not Found")) 

(def app 
    (wrap-defaults app-routes site-defaults)) 

Теперь, после изменения чего-либо в app-routes определения (например, изменение «Динамическая страница» текст к чему-то еще, или изменение строки соответствия URI), я не получаю обновленный текст/маршруты в браузере. Но, когда немного изменив app-routes определение

(defn dynfn [] "Dynamic page fn") 
(defroutes app-routes 
    (GET "/*.do" [] (dynfn)) 
    (route/not-found "Not Found")) 

я действительно получают динамические обновления при изменении значения возвращаемого dynfn. Кроме того, следуя советам из this article и модификации app определение

(def app 
    (wrap-defaults #'app-routes site-defaults)) 

(обратите внимание, что #' прозрачно создает вар для app-routes) также помогает!

Почему это так? Есть ли другой способ получить действительно динамическое поведение в defroutes?

Спасибо!

ответ

8

#'app-routes - это макрос читателя, который расширяется до (var app-routes). Когда var используется, как если бы это была функция, он разыменовывается заново каждый вызов, а затем вызывается значение, возвращаемое этим деревом.

Если вы должны были поставить app-routes в качестве аргумента, компилятор даст разыменованное значение wrap-defaults, а когда вар обновляется, предыдущее значение не изменяется, поэтому изменение вара не изменяет поведение app.

Следующая РЕПЛ транскрипт может быть поучительным:

user=> (defn foo [] "original") 
#'user/foo 
user=> (defn caller [f] #(f)) 
#'user/caller 
user=> (def call-foo-value (caller foo)) 
#'user/call-foo-value 
user=> (call-foo-value) 
"original" 
user=> (def call-foo-var (caller #'foo)) 
#'user/call-foo-var 
user=> (call-foo-var) 
"original" 
user=> (defn foo [] "changed") 
#'user/foo 
user=> (call-foo-value) 
"original" 
user=> (call-foo-var) 
"changed" 
+1

Спасибо за совершенное объяснение. Я действительно хотел бы, чтобы он был включен в дополнительные учебники по Ring/Compojure. Спасибо! – siphiuel

 Смежные вопросы

  • Нет связанных вопросов^_^