Clojure 为什么我必须在这段代码中使用(flush)?

Clojure 为什么我必须在这段代码中使用(flush)?,clojure,Clojure,这是我第一次接触Clojure,所以我试着写一个简单的脚本,提供基于维基百科的翻译(欢迎评论) 问题是:当我从translate中删除(flush)时,脚本输出nil而不是translated word。为什么?我显然错过了什么,但是什么呢?(println translations)给出了与flush相同的结果(起初我尝试使用doseq/doall,但没有结果) (使用Clojure 1.2并在eclipse 3.7.2中以逆时针方向进行测试) 守则: (ns wiki-translate

这是我第一次接触Clojure,所以我试着写一个简单的脚本,提供基于维基百科的翻译(欢迎评论)

问题是:当我从translate中删除(flush)时,脚本输出nil而不是translated word。为什么?我显然错过了什么,但是什么呢?(println translations)给出了与flush相同的结果(起初我尝试使用doseq/doall,但没有结果)

(使用Clojure 1.2并在eclipse 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"))
(ns维基翻译)
(:require[clojure.contrib.http.agent:as h])
)
(defn获取url
([lg术语](str“http://”lg.wikipedia.org/wiki/“术语))
)
(defn获取url)
([url](h/string(h/http代理url)))
)
(defn获取翻译
([cnt](应用排序地图(展平(用于[s(re-seq#“(?i)interwiki-([^\“]+).*wiki\/([^\“]+)\”*/a>“cnt)][(S1)(S2)])))
(defn翻译
[术语src lg tgt lg](
(def翻译(获取翻译(获取url(获取url src lg term)))
(齐平)
(如果(包含?翻译tgt lg)(获取翻译tgt lg)”)
)           
)
(println(翻译为“Shark”“en”“fr”))

您需要在translate函数中使用
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>")))   
(defn翻译)
[术语src lg tgt lg]
(let[翻译(获取翻译(获取url(获取url src lg term)))]
(如果(包含?翻译tgt lg)(获取翻译tgt lg)”)
let用于为let块中的表单创建本地绑定。使用def会创建全局绑定(在当前命名空间中)。因此,基本上,在执行现有代码后,可以在函数外部使用var
translations
,因为它是在全局范围内使用def创建的

我不太清楚flush与def有什么关系才能使其正常工作。也许有人对def的工作原理有深入的了解,可以对此有所了解,这肯定是一件有趣的事情

更新:


有趣的是,将函数体包装在
do
中可以使其与
def
一起工作而不使用flush,但这不是您应该做的事情。使用
let
是首选方法。
do
用于执行一系列具有副作用的表达式,因此似乎
def
是一种副作用表达式使用
do
flush
可以“实际”执行副作用操作。

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>"))
因为第一个表单返回要定义的Var,并及时定义它,以便第二个表单在查找中成功。当您将Var作为一个函数调用时,这是一个映射,因此,效果是在映射中查找“Requin”。映射没有带有该键的元素,因此值为nil

(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
,如果在映射中找不到
nil
,则返回“Requin”作为默认值

((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")