这本书说:
“请注意,我们必须从处理程序创建一个var才能使用此中间件
上班.这是确保包含当前的Var对象所必需的
处理函数返回.如果我们使用处理程序而不是应用程序
只能看到功能的原始值,并且不会反映出变化.“
我真的不明白这意味着什么,变量类似于c指针?
(ns ring-app.core (:require [ring.adapter.jetty :as jetty] [ring.util.response :as response] [ring.middleware.reload :refer [wrap-reload]])) (defn handler [request] (response/response (str "<html>/<body> your IP is: " (:remote-addr request) "</body></html>"))) (defn wrap-nocache [handler] (fn [request] (-> request handler (assoc-in [:headers "Pragma"] "no-cache"))))
这是处理程序调用:
(defn -main [] (jetty/run-jetty (wrap-reload (wrap-nocache (var handler))) {:port 3001 :join? false}))
解决方法
假设你定义fred如下:
(defn fred [x] (+ x 1))
这里实际上有三件事.首先,弗雷德是一个象征.符号fred(无引号)与关键字:fred(由leading:char标记)和字符串“fred”(两端用双引号标记)之间存在差异.对于Clojure,每个人都由4个字符组成;即,关键字的冒号和字符串的双引号都不包含在它们的长度或组成中:
> (name 'fred) "fred" > (name :fred) "fred" > (name "fred") "fred"
唯一的区别是如何解释它们.字符串用于表示任何类型的用户数据.关键字意味着以可读的形式表示程序的控制信息(与“幻数”相反,例如1 =左,2 =右,我们只使用关键字:左和右.
符号意味着指向事物,就像在Java或C中一样.如果我们说
(let [x 1 y (+ x 1) ] (println y)) ;=> 2
然后x指向值1,y指向值2,我们看到打印结果.
(def …)表单引入了一个不可见的第三个元素var.所以,如果我们说
(def wilma 3)
我们现在要考虑3个对象. wilma是一个符号,它指向一个var,而var又指向值3.当我们的程序遇到符号wilma时,会对其进行求值以查找var.同样,var被评估为产生值3.所以它就像是C中指针的2级间接.因为符号和var都是“自动评估”,所以这是自动且不可见的,你不会不得不考虑var(事实上,大多数人并不真正意识到隐形中间步骤甚至存在).
对于我们上面的函数fred,存在类似的情况,除了var指向匿名函数(fn [x](x 1))而不是像Wilma那样的值3.
我们可以将var的自动评估“短路”:
> (var wilma) #'clj.core/wilma
要么
> #'wilma #'clj.core/wilma
读者宏#'(pound-quote)是调用(var …)特殊形式的简写方式.请记住,像var这样的特殊形式是内置的编译器,如’if’或’def’,与常规函数不同. var特殊形式返回附加到符号wilma的var对象. clojure REPL使用相同的速记打印var对象,因此两个结果看起来都一样.
获得var对象后,将禁用自动评估:
> (println (var wilma)) #'clj.core/wilma
如果我们想要达到wilma指向的值,我们需要使用var-get:
> (var-get (var wilma)) 3 > (var-get #'wilma) 3
同样的事情适用于fred:
> (var-get #'fred) #object[clj.core$fred 0x599adf07 "clj.core$fred@599adf07"] > (var-get (var fred)) #object[clj.core$fred 0x599adf07 "clj.core$fred@599adf07"]
其中#object [clj.core $fred …]的东西是Clojure将函数对象表示为字符串的方式.
关于Web服务器,它可以通过var告诉?函数或其他函数,如果提供的值是处理函数或指向处理函数的var.
如果您键入以下内容:
(jetty/run-jetty handler)
double auto-evaluation将产生处理函数对象,该对象被传递给run-jetty.相反,如果您输入:
(jetty/run-jetty (var handler))
那么指向处理函数对象的var将被传递给run-jetty.然后,run-jetty将必须使用if语句或等效语句来确定它已接收到的内容,如果已收到var而不是函数,则调用(var-get …).因此,每次通过(var-get …)将返回var当前指向的对象.因此,var的作用类似于C中的全局指针,或者Java中的全局“引用”变量.
如果将函数对象传递给run-jetty,它会将“本地指针”保存到函数对象中,并且外部世界无法更改本地指针所引用的内容.
您可以在此处找到更多详细信息
> http://clojure.org/reference/evaluation
> http://clojure.org/reference/vars