首先声明一点,这篇短文不是要挑起语言之间的关于孰优孰劣的论战,只是但愿经过一个小需求,让你们可以对比体会一下函数式编程和面向对象编程的差别(包括理念和语法上的)。程序员
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 代码,这样两边的系统就对接上了。程序猿的语言世界真的好复杂!设计