前回のClojureでHadoopのサンプルのうち、定型処理っぽい部分をマクロにしてみました。
プロジェクト名はClojure + Cloud = Cloudureです。
名前負けしてます。まだいまいち。(ClojureもHadoopもそんな使った事ない。。)
2010/03/07 Clojarsにデプロイしました(namespaceが変えました)
マクロの定義はいまのとここんな感じ。使い方は
;; Mapper、Reducerを別関数にする場合 (defn hello-map [key value context] (.write context (Text. key) (IntWritable. (Integet/parseInt value))) ) (defn hello-reduce [key values context] (.write context key (IntWritable. (reduce + (map #(.get %) values)))) ) (defmapreduce hello :mapper hello-map :reducer hello-reduce )
;; Mapper、Reducerもいっしょに定義する場合
(defmapreduce hello
:mapper ([key value context] (.write context (Text. key) (IntWritable. (Integet/parseInt value))))
:reducer ([key values context] (.write context key (IntWritable. (reduce + (map #(.get %) values)))))
)
前者を展開した場合、
(do
(gen-class
:name
org.clojars.making.cloudure.core.hello.mapper
:extends
org.apache.hadoop.mapreduce.Mapper
:prefix
"hello-mapper-")
(defn hello-mapper-map [G__2310 G__2311 G__2312 G__2313]
(hello-map G__2311 G__2312 G__2313))
(gen-class
:name
org.clojars.making.cloudure.core.hello.reducer
:extends
org.apache.hadoop.mapreduce.Reducer
:prefix
"hello-reducer-")
(defn hello-reducer-reduce [G__2314 G__2315 G__2316 G__2317]
(hello-reduce G__2315 G__2316 G__2317))
(defn get-hello-job
([] (get-hello-job true))
([set-jar?]
(let [job (org.apache.hadoop.mapreduce.Job.)]
(if set-jar?
(.setJarByClass job (forName "org.clojars.making.cloudure.core")))
(doto
job
(.setMapperClass
(forName "org.clojars.making.cloudure.core.hello.mapper"))
(.setReducerClass
(forName "org.clojars.making.cloudure.core.hello.reducer")))))
{:tag java.lang.Class}))
後者は
(do
(gen-class
:name
org.clojars.making.cloudure.core.hello.mapper
:extends
org.apache.hadoop.mapreduce.Mapper
:prefix
"hello-mapper-")
(defn hello-mapper-map [this key value context]
(.write context (Text. key) (IntWritable. (parseInt value))))
(gen-class
:name
org.clojars.making.cloudure.core.hello.reducer
:extends
org.apache.hadoop.mapreduce.Reducer
:prefix
"hello-reducer-")
(defn hello-reducer-reduce [this key values context]
(.write context key (IntWritable. (reduce + (map #(.get %) values)))))
(defn get-hello-job
([] (get-hello-job true))
([set-jar?]
(let [job (org.apache.hadoop.mapreduce.Job.)]
(if set-jar?
(.setJarByClass job (forName "org.clojars.making.cloudure.core")))
(doto
job
(.setMapperClass
(forName "org.clojars.making.cloudure.core.hello.mapper"))
(.setReducerClass
(forName "org.clojars.making.cloudure.core.hello.reducer")))))
{:tag java.lang.Class}))
前回のサンプルのdefmapreduce版はこんな感じ。
まだまだですね。もっとHadoopを使って慣れながら改良していきたいと思います。
一応Cloudureを使うには、Clojarsに上げてあるので、project.cljに↓を追加すればOK
[org.clojars.making/cloudure "0.1.0-SNAPSHOT"]
コメント・アドバイスがあれば@makingまで。
Created at : 2010-03-01 02:34:55
Updated at : 2010-03-10 03:01:31
Category : Programming::Lisp::Clojure
LinuxやMacOSXの場合はREADME読んで。
バイナリが用意されているので適当な場所にDLして展開。
展開してできたフォルダのパスをCASSANDRA_HOMEとして環境変数に設定する。
%CASSANDRA_HOME%\bin\cassandra.batをダブルクリック。あら簡単。
ログやデータはデフォルトで%CASSANDRA_HOME%\lib\var以下にできる模様。(なんか変なドライブまでできとる。。。)
%CASSANDRA_HOME%\bin\cassandra-cli.batをダブルクリック。
connectを実行した後はREADME通り。
cassandra> connect localhost/9160 Connected to localhost/9160 cassandra> set Keyspace1.Standard1['jsmith']['first'] = 'John' Value inserted. cassandra> set Keyspace1.Standard1['jsmith']['last'] = 'Smith' Value inserted. cassandra> set Keyspace1.Standard1['jsmith']['age'] = '42' Value inserted. cassandra> get Keyspace1.Standard1['jsmith'] => (column=last, value=Smith, timestamp=1267619133099) => (column=first, value=John, timestamp=1267619123162) => (column=age, value=42, timestamp=1267619142661) Returned 3 results.
Created at : 2010-03-03 21:26:36
Updated at : 2010-03-03 22:32:06
Category : Middleware::NoSQL::Cassandra
Clojureはマクロ定義内のシンボルを名前空間で修飾する。シンボル束縛を回避するためであり、バグを防いでくれるが、次のような書き方をしたいときはNG。
(defmacro foo [x]
`(defn ~x [x]
x
)
)
user> (macroexpand-1 '(foo aaa)) (clojure.core/defn aaa [user/x] user/x) user> (foo aaa) Can't use qualified name as parameter: user/x [Thrown class java.lang.Exception]
シンボル束縛を強制的に行うためには~'をつける。
(defmacro foo [x]
`(defn ~x [~'x]
~'x
)
)
user> (macroexpand-1 '(foo aaa)) (clojure.core/defn aaa [x] x) user> (foo aaa) #'user/aaa user> (aaa 100) 100
使うときは要注意。
尤も、このケースでは(gensym)を使うべきなのだが。。。
→ (追記:2010/03/03)Clojureはマクロ内で使うシンボルの末尾に「#」をつければ勝手にgensymしてくれます。
user> (defmacro foo [x] `(defn ~x [x#] x#)) #'user/foo user> (macroexpand-1 '(foo aaa)) (clojure.core/defn aaa [x__4956__auto__] x__4956__auto__)
Created at : 2010-02-26 03:22:45
Updated at : 2010-03-03 12:23:14
Category : Programming::Lisp::Clojure