Geohash rewritten with Clojure

Sorry but this is another release announcement.

I just rewrite my node-geohash module with clojure. You can include it with leiningen according to the instructions shows here. The project is hosted on bitbucket this time. The API is rather simple, please just follow the README doc.

It’s totally different experience to write such kind of algorithm in a functional language. You have to translate loops to recursions, also make sure they are available for tail recursion optimization. I really enjoy coding in clojure.

Clojure-Control plugin for leiningen

Clojure-Control is the clojure port of node-control, developed by killme2008. Clojure-Control allows you to define clusters and tasks in a DSL and execute them with simple command.

Lein-control is a leiningen(clojure build tool) plugin, with which you can integrate Clojure-Control into your build tasks. It could be helpful to execute deployment tasks on several machines.

To use lein-control, simply add this to your project.clj . And download dependencies with lein deps.
:dev-dependencies [[lein-control "0.1.0"]]

Create a sample control file in your project home:
lein control init

Check your cluster configuration:
lein control show cluster-name

Execute tasks against particular cluster:
lein control run cluster-name task-name

Enjoy your deployment !

Reddit.clj: clojure wrapper for Reddit API

As mentioned in Rage Viewer, I have another clojure library to communicate with Reddit. Now it’s public available as “reddit.clj“.

Reddit.clj is managed with leiningen. The current reddit.clj release is 0.1.3 0.2.0. You can include it in your project.clj:

(defproject xxxx "1.0.0-SNAPSHOT"
  :dependencies [[reddit.clj "0.2.0"]])

This is a simple tutorial for you to getting started :

;; include reddit.clj
(require '[reddit.clj.core :as reddit])
;; create a reddit client with reddit/login.
;; you can also ignore the arguments to use it
;; anonymously
(def rc (reddit/login "your-reddit-name" "your-reddit-passwd"))

;; load reddits from subreddit "clojure", and print titles
(doseq
 [title (map :title (reddit/reddits rc "clojure"))]
  (println title))

;; enhance reddit client to enable writing, for login user only
;; this operation will retrieve reddit user modhash under the hood
(def rc (reddit/enhance rc))

;; vote-up a thing on reddit
(reddit/vote-up rc "t3_iz61z")

;; you may also submit links to reddit.
;; permalink will be returned when success.
;; be careful to use this API because reddit may ask you for a
;; captcha. But as a library, reddit.clj will return nil on this case.
;; use it at your own risk.
(reddit/submit-link rc "title" "url" "subreddit-name")

Detailed API documents are listed here.

This library should be useful to crawl data from reddit which is rich of information. Reddit.clj is hosted on github.

Weekend Project: RageViewer

“Weekend is for weekend projects.”

介绍Weekend Project前,先说个事。早上HN上有人说:你们这些个人,自个偷偷摸摸搞了半年一年的东西,然后发到HN上说这是两天就搞定的weekend project,你们恶心不恶心。本人郑重声明,下面这个东西确实是标准的weekend project,只用了周六下午和晚上的时间,结果周日还因为元气大伤只改了一点小东西。因为确实只有不到两天的effort,所以就不发到HN上丢人现眼了。

话说,比起HN,我更常看reddit。于是就有了这个weekend project,Rage Viewer,可以浏览reddit ffffffffuuuuuuu上最新的rage comic。

功能很简单,唯一值得一提的是它是统统用clojure写成的,后端是clojure,前端是最近公布的clojurescript编译的js。之所以这么搞,不为别的,只为cool。这个和每天早晨五点起床化妆是一个道理。

在github上可以找到这个项目,他可以随意跑在任何地方,只要三个步骤:

  • git clone git://github.com/sunng87/rageviewer.git
  • lein deps
  • lein ring server

欢迎feedback。

ClojureScript Recipes

一周前左右有人说javascript是assembly language for the web, 结果一周不到clojurescript发布了。闹了半天clojure 1.3迟迟不发布是因为effort都迫不及待地转移到向javascript迁移上去了。简单地说cljs是clojure在javascript上的实现,通过cljsc可以把clojure编译成js,运行在浏览器里或是Node环境里。

目前clojurescript还没有正式的发布版本,需要从github签出开发版本。

  1. cljs是在Oracle JDK上开发的,引用了sun.org.mozilla.javascript.internal.Context,这个类在OpenJDK里叫做sun.org.mozilla.javascript.Context。所以没有办法,暂时只能在Oracle JDK上用clojurescript。
  2. cljs自带的所有脚本,启动jvm时,heap size都是开2G的。可怜我所有的内存才2.5G,还是分布在两台电脑上(#@&*……@¥@!)。不过我手动把它改为512M后cljsc还是依然可以正常运行的。
  3. cljs与javascript的互操作是最麻烦的部分,一般情况cljs通过(js*)这个form来访问javascript数据和对象,比如访问document:(js* “document”)。进而访问getElementById时,即(.getElementById (js* “document”) “some-id”)。
  4. cljs访问js对象时,通过(aget)而不是(.属性名),例如(aget rage “ups”)编译后为rage.ups,如果(.ups rage)就会被当作函数调用。不过奇怪的是如果(.title rage)依然会被编译成rage.title。这种不一致的情况在对.url也存在。当然用aget是可以获得一致的结果的(aget在clojure里是根据索引取java数组的form,在cljs里可以支持js object了)。
  5. 当访问无参数的js对象时,cljs与clojure有不同。例如在clojure里(.toString date),而在cljs里,这样写编译的结果是date.toString,注意没有括号,直接访问这个function对象了。所以在cljs里,正确的写法有些变化(. date (toString))。
  6. 创建js对象,可以通过(js-obj)这个form
  7. 修改dom属性,需要用(set!)这个form,如 (set! (.src img) “http://xxx”)。如果把cljs用在网页里,类似这样的操作比比皆是,这和clojure大不相同。
  8. cljs里没有STM,暂时也不支持ref。可以直接用def定义变量,随意地访问和修改,js环境是单线程环境。
  9. 对于要对外访问的方法,在声明时加上^:export可以让编译器不修改方法的名字。

用cljs开发有趣归有趣,调试还是很困难的,建议开发的时候就写好打log的代码(js* “console.log”),因为目前cljsc编译的速度也不快,反复地修改代价还是挺高的。当然,为了cool,以上都不是问题。