首先聲明一點,這篇短文不是要挑起語言之間的關於孰優孰劣的論戰,只是但願經過一個小需求,讓你們可以對比體會一下函數式編程和麪向對象編程的差別(包括理念和語法上的)。程序員
Clojure 是什麼?
Clojure 是運行在 Java 虛擬機(JVM)上的一種 Lisp 方言,她比 Common Lisp 更強調純函數式編程,同時擁有複雜的「宏」。具體能夠看 CSDN 上的一篇介紹文章 現實世界的LISP:Clojure語言初探 和知乎上的討論 請評價一下Clojure語言的設計redis
咱們在開發過程當中常常會碰到這個需求,要對一個字符串進行哈希,而後當成 key 存入 redis。咱們準備使用 Java 的 SHA-512 哈希算子來作第一步運算,而且把結果再作一次 Base64 編碼轉換。算法
好的,那咱們接下來就看看在兩種語言中如何作到這一點吧。編程
程序猿的世界,代碼說明一切,咱們直接上代碼吧,算法的入口是一個名爲 hash-name 函數:函數式編程
(defonce ^:private hash-key "universal_redis_hash_key") (defn hash-name [k] (.substring ^String (:password (digest hash-key k)) 0 4)) (defn digest ([salt passwd] (digest "SHA-512" 512 salt passwd)) ([hashalg iterations salt passwd] (let [jhash (MessageDigest/getInstance hashalg) new-pass (b64-encode (digester jhash salt passwd iterations))] {:salt salt :password new-pass}))) (defn- digester [^MessageDigest hasher ^String salt ^String pw-clear iter] {:tag String} (letfn [(hashme [hv] (letfn [(oneround [hv] (do (.reset hasher) (.digest hasher hv)))] (nth (iterate oneround hv) iter)))] (.reset hasher) (.update ^MessageDigest hasher (.getBytes salt)) (.update ^MessageDigest hasher (.getBytes pw-clear)) (hashme (.digest hasher)))) (defn b64-encode [^bytes b] {:tag String} (Base64/encodeBase64String b))
不知道能徹底看懂上面代碼的人有多少。要是咱們用Java寫出來的話,相信不少人會拍着腦殼:原來如此!函數
仍是同樣,直接上代碼,這裏只有一個函數 hashName:編碼
private final static String hashKey = 「universal_redis_hash_key"; public static String hashName(String salt, String pw, int iter) { try { MessageDigest digest = MessageDigest.getInstance("SHA-512"); digest.reset(); digest.update(salt.getBytes()); digest.update(pw.getBytes()); byte[] temp = digest.digest(); for (int i = 0; i < iter; i++) { digest.reset(); temp = digest.digest(temp); } String result = Base64.encodeBase64String(temp); return result.substring(0, 4); } catch (Exception ex) { ex.printStackTrace(); } return ""; }
對這兩門語言的見解,或許有人會從通俗易懂上進行比較,有人會從優雅嚴謹性上進行批判,我沒有任何傾向性,這就是一個仁者見仁智者見智的問題。翻譯
我只想補充說一下這種對比的由來。我司的程序員中 Clojure 粉較多,不少程序都是用 Clojure 寫的。最近要跟其餘公司的小夥伴合做搭一個服務,兩邊都須要採用一樣的關鍵字哈希算法。我找到一塊咱們的實現片斷,發了過去。可是對方不懂 Clojure,他們使用的是 Ruby;我懂 Clojure 可是不懂 Ruby,兩我的都快無法交流了。最後咱們一商量,你們都能懂 Java,因此我先把 Clojure 代碼翻譯成 Java 代碼,而後他再轉換成 Ruby 代碼,這樣兩邊的系統就對接上了。程序猿的語言世界真的好複雜!設計