2012-03-18 11 views
3

それはClojureのと私の最初の接触ですので、私はウィキペディアに基づいて翻訳を提供して簡単なスクリプト(任意の批評家/コメントは歓迎されている)なぜこのコードで(フラッシュする)必要がありますか?

を書き込もうとしました、問題がある:私はから(フラッシュ)を削除すると、を翻訳スクリプトは翻訳された単語の代わりにnilを出力します。なぜですか?私は明らかに何かを欠いているが、何? (printlnの翻訳)は、同じ結果をもたらすこと(私はdoseq/DOALLと試み始めに、しかし結果なし)フラッシュ

(Clojureの1.2使用方法および反時計と日食3.7.2でテスト)

コード:

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

レットをトン使用されている:あなたはtranslate関数の内部でletではなくdefを使用する必要が

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

答えて

4

translateの機能には余分なレベルのカッコがあり、偶然には(flush)が機能します。 (flush)ことなく、コードはClojureのは、2つのサブフォームを評価する機能としての第1を呼び出すことによってits evaluation rulesによれば、このフォームを評価

((def translations (get-translations (fetch-url (get-url src-lg term)))) 
(if (contains? translations tgt-lg) (get translations tgt-lg) "<NOT FOUND>")) 

あります。サブフォームを評価して第一形態はvarが定義されて戻り、第二の形態は、ルックアップに成功するための時間でそれを定義するため、フォームが

(#'translations 
"Requin") 

となります。 Varを関数として呼び出すと、the call is delegated to the value of the Var(マップ)であり、map implements function call as look-up以降、マップ内で「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 
"Requin") 

に評価され、再び#'translationsの値であるマップが呼び出されます。今回は、nilが検索されず、nilがマップに見つからない場合に返されるデフォルト値として「Requin」が返されます。

3

o letブロック内のフォームのローカルバインディングを作成します。 defを使用すると、現在の名前空間にグローバルバインディングが作成されます。したがって、基本的には終了コードを実行した後に、グローバルスコープでdefを使用して作成されているため、関数の外にある変数transalationsを使用することができます。

defを動作させるためにflushと何が関係しているのか正確にはわかりません。おそらく、def動作の仕組みを深く知っている誰かが、これについていくつかの光を当てることができ、それは確かに知ることは興味深いことでしょう。

UPDATE:

興味深いことにdoに関数本体を包むが、それはフラッシュなしでdefで動作しますが、それはあなたが行うべきものではありません。 letを使用するのが好ましい方法です。 doは、副作用のある一連の式を実行するために使用されるため、defは副作用式の一種で、doまたはflushを使用すると、実際には副作用操作が実行されます。

関連する問題