It’s my first contact with Clojure, so I tried to write simple script which provides translation based on wikipedia (any critics / comments are welcome)
The problem is: when I remove (flush) from translate, script outputs nil instead of translated word. Why is that? I am clearly missing something, but what? (println translations) gives same result that flush (at the beginning I tried with doseq / doall, but without results)
(Using Clojure 1.2 and testing in eclipse 3.7.2 with counterclockwise)
The code:
(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"))
The
translatefunction has an extra level of parentheses, and(flush)makes it work by accident. Without(flush), the code isClojure evaluates this form according to its evaluation rules by evaluating the two sub-forms and calling the first as a function. With the sub-forms evaluated, the form becomes
because the first form returns the Var being defined, and defines it in time for the second form to succeed in the look-up. When you call a Var as a function, the call is delegated to the value of the Var, which is a map, and since map implements function call as look-up, the effect is to look up “Requin” in the map. The map has no element with that key, so the value is nil.
With the
(flush)added in between, the same process happens:is first evaluated into
and again the map that is the value of
#'translationsis called. This time the effect is to look upnil, with “Requin” as the default value returned in casenilis not found in the map.