为什么我必须在这段代码中使用(flush)?
这是我用Clojure的第一次接触,所以我试着写简单的脚本,它提供了基于*翻译(任何批评/评论,欢迎)为什么我必须在这段代码中使用(flush)?
的问题是:当我删除(齐平)翻译,脚本输出nil而不是翻译的单词。这是为什么?我明显错过了一些东西,但是什么? (的println翻译)给出相同的结果是齐平(在我与doseq/DOALL尝试开始,但没有效果)
(使用Clojure的1.2和3.7.2蚀逆时针方向测试)
的代码:
(ns wiki-translate
(:require [clojure.contrib.http.agent :as h])
)
(defn get-url
([lg term] (str "http://" lg ".wikipedia.org/wiki/" term))
)
(defn fetch-url
([url] (h/string (h/http-agent url)))
)
(defn get-translations
([cnt] (apply sorted-map (flatten (for [s (re-seq #"(?i)interwiki-([^\"]+).*wiki\/([^\"]+)\".*/a>" cnt)] [(s 1) (s 2)])))))
(defn translate
[term src-lg tgt-lg] (
(def translations (get-translations (fetch-url (get-url src-lg term))) )
(flush)
(if (contains? translations tgt-lg) (get translations tgt-lg) "<NOT FOUND>")
)
)
(println (translate "Shark" "en" "fr"))
的translate
功能有括号的额外的水平,(flush)
使得意外工作。而不(flush)
,将码是
((def translations (get-translations (fetch-url (get-url src-lg term))))
(if (contains? translations tgt-lg) (get translations tgt-lg) "<NOT FOUND>"))
的Clojure根据its evaluation rules通过评估两个子形式和呼叫第一作为函数评估该形式。与子形式进行评价的形式变得
(#'translations
"Requin")
因为第一形式,返回所定义的VAR,并且它定义了在时间为所述第二形式中的查找成功。当你调用一个VAR的功能,the call is delegated to the value of the Var,这是一张地图,而且由于map implements function call as look-up,效果是查找“Requin”在地图上。该地图没有包含该键的元素,因此该值为零。
随着之间,相同的过程发生在加入的(flush)
:
((def translations (get-translations (fetch-url (get-url src-lg term))))
(flush)
(if (contains? translations tgt-lg) (get translations tgt-lg) "<NOT FOUND>"))
首先计算到
(#'translations
nil
"Requin")
,并再次向地图是#'translations
值被调用。这次效果是查找nil
,并且在地图中未找到nil
的情况下将“Requin”作为默认值返回。
您需要使用let
而非def
的转换函数内部:
(defn translate
[term src-lg tgt-lg]
(let [translations (get-translations (fetch-url (get-url src-lg term)))]
(if (contains? translations tgt-lg) (get translations tgt-lg) "<NOT FOUND>")))
让利是用于ŧ o为let块中的表单创建本地绑定。使用def创建一个全局绑定(在当前命名空间中)。所以基本上在执行完退出代码之后,你可以在函数的外部使用var transalations
,因为它是在全局范围内使用def创建的。
我并不完全相信平与DEF做,使其工作。可能有人对def的工作方式有深入的了解,这可能会对此有所了解,那肯定是一件有趣的事情。
UPDATE:
有趣的是包装函数体中do
使得它与def
工作,无需刷新,但是这是不是你应该做的。使用let
是首选的方法。 do
用于执行一系列表达的有副作用,因此似乎def
是一种副作用表达和使用do
或flush
使得它“实际上”执行副作用动作进行说明。