Clojure Ring/Compojure REPL中的动态处理程序更新

sip*_*uel 3 clojure compojure ring read-eval-print-loop

我使用了一个新的Compojure Leiningen项目lein new compojure test.Web服务器由lein repl然后运行

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

路由和应用程序处理程序规范是微不足道的:

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

(def app
  (wrap-defaults app-routes site-defaults))
Run Code Online (Sandbox Code Playgroud)

现在,在更改app-routes定义中的任何内容后(例如,将"动态页面"文本更改为其他任何内容,或修改URI匹配字符串),我不会在浏览器中获得更新的文本/路由.但是,当app-routes稍微改变定义时

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

我在更改返回值时会获得动态更新dynfn.另外,遵循本文的建议并将app定义修改为

(def app
  (wrap-defaults #'app-routes site-defaults))
Run Code Online (Sandbox Code Playgroud)

(注意#'透明地创建一个var app-routes)也有帮助!

为什么会这样?有没有其他方式可以获得真正的动态行为defroutes

谢谢!

noi*_*ith 8

#'app-routes是一个扩展到的读者宏(var app-routes).当var被用作函数时,它会在每次调用时重新解除引用,然后调用该deref返回的值.

如果您要提供app-routes参数,编译器将给出解除引用的值wrap-defaults,并且当更新var时,之前的值不会更改,因此更改var不会更改其行为app.

以下repl成绩单可能具有指导意义:

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"
Run Code Online (Sandbox Code Playgroud)