从一小段代码看 Clojure 和 Java 解决问题的差异

发布时间:2019-11-19 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了从一小段代码看 Clojure 和 Java 解决问题的差异脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

首先声明一点,这篇短文不是要挑起语言之间的关于孰优孰劣的论战,只是希望通过一个小需求,让大家能够对比体会一下函数式编程和面向对象编程的差异(包括理念和语法上的)。


Clojure 是什么
Clojure 是运行在 Java 虚拟机(JVM)上的一种 Lisp 方言,她比 Common Lisp 更强调纯函数式编程,同时拥有复杂的「宏」。具体可以看 CSDN 上的一篇介绍文章 现实世界的LISP:Clojure语言初探知乎上的讨论 请评价一下Clojure语言的设计

要解决一个什么问题

我们在开发过程中经常会碰到这个需求,要对一个字符串进行哈希,然后当成 key 存入 redis。我们准备使用 Java 的 SHA-512 哈希算子来做第一步运算,并且把结果再做一次 Base64 编码转换

好的,那我们接下来就看看在两种语言中如何做到这一点吧。

Clojure 的解法

程序猿的世界,代码说明一切,我们直接上代码吧,算法的入口是一个名为 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写出来的话,相信很多人会拍着脑袋:原来如此!

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 代码,这样两边的系统就对接上了。程序猿的语言世界真的好复杂!

脚本宝典总结

以上是脚本宝典为你收集整理的从一小段代码看 Clojure 和 Java 解决问题的差异全部内容,希望文章能够帮你解决从一小段代码看 Clojure 和 Java 解决问题的差异所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。