O uso de namespaces em clojure pode ser bem simples, mas pode ser bem complicado. Vou focar no simples :)
O namespace de clojure está próximo da declaração pacote/classe no java, assim o padrão é o mesmo para nomenclatura (apesar de poder variar), dessa forma o arquivo clojure em src/twitter/search.clj teria normalmente o ns (ns = namespace) twitter.search.
A declaração básica de um namespace é a através do macro “ns”:
(ns twitter.search)
Com os arquivos definidos com seus devidos namespace, e o classpath (cp) do java configurado certo (apontando para o src/, por exemplo, você pode chamar outros arquivos clojure pelo seu ns:
(ns twitter.main (:require twitter.search) )
Agora você teria o ns twitter.search disponível em seu main, mas a forma mais prática é a seguir:
(ns twitter.main (:require [twitter.search :as search) )
Assim o conteúdo do ns twitter.search está no simbolo alias search, dessa forma para chamar a função "search-timeline" do twitter.search você faz:
(search/search-timeline "clojure")
Outra forma útil no ns é o "use", que traz os simbolos do outro ns para o ns atual, assim:
(ns twitter.main (:use twitter.search)) (search-timeline "clojure")
Agora podemos também compilar nossa aplicação clojure, tendo por exemplo a seguinte estrutura de arquivos:
/app /app/src /app/src/twitter /app/src/twitter/main.clj /app/src/twitter/search.clj /app/classes /app/libs
Considerando que seus .jars do clojure estão no libs, conforme este texto, você deve então passar a lancar o clojure com o seguinte comando (veja o novo classpath):
java -cp ./:./src/:./classes/:libs/clojure.jar:libs/clojure-contrib.jar clojure.main $1
Agora podemos definir um método main no nosso twitter/main.clj :
(ns twitter.main (:require [twitter.search :as search])) (defn -main [word] (let [tweets (search/search word)] (println (reduce (fn [t0 t1] (str t0 "\n" (get t1 "at") " @" (get t1 "from") " : " (get t1 "text") )) "Search result" tweets )) ))
E o twitter/search.clj:
(ns twitter.search (:use clojure.contrib.json.read) (:require [clojure.contrib.http.agent :as http ]) )
(defn search [word] (let [json (http/string (http/http-agent (str "http://search.twitter.com/search.json?q=" word)) )] (map (fn [tweet] {"from" (get tweet "from_user") "text" (get tweet "text") "at" (get tweet "created_at")}) (get (read-json json) "results")) ) )
Como pode-se ver usamos tanto o use como o require, assim como as funções mega-hyper-uteis de map e reduce para excercício.
Mais então para compilar o projeto, lance o REPL executando apenas o “./clj” e mande compilar com:
(compile 'twitter.main)
Agora suas classes estão na pasta classes, você pode executar a aplicação rodando:
$ java -cp ./libs:./classes:./libs/clojure.jar:./libs/clojure-contrib.jar twitter.main clojure
Assim vai rodar o -main recebendo o “clojure” como argumento. Crie agora o script de start-up e pronto.
Bonus: uma versão em um script de 30 linhas formatadas de uma busca no twitter com clojure. Basta executar o .clj.