五年 Clojure 使用者浅谈 Clojure 语言的设计 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
LeanCloudRRY
V2EX    Clojure

五年 Clojure 使用者浅谈 Clojure 语言的设计

  •  1
     
  •   LeanCloudRRY 2015-08-04 11:40:25 +08:00 8203 次点击
    这是一个创建于 3746 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近不知道为什么,大家好像对函数式编程的兴趣又起来了,前阵子同事在知乎有一个比较精彩的回答,转到这里。说硬不硬,解一下也好,和 Clojure 爱好者分享一下也好。

    基于 JVM 的决定

    Clojure 能够吸引人的很重要一点是它是 JVM 之上的语言,这个决定非常关键。

    • 首先,因为根植于 JVM 之上,并且做到了跟 Java 语言的相互调用,它能吸引很多成熟的 Java 开发者。

    • 其次,它可以使用 Java 社区丰富的开源软件,不需要从头去构建一个社区,你可以看到很多 Clojure 开源代码都是简单地包装 Java 的开源包,但是通过 Clojure 高度抽象简单的语法提供更便利的使用的方式;

    • 第三,由于 JVM 平台本身的高度成熟和优化,clojure 的编译器生成的 byte code 跟 Java 编译器生成的 byte code 并无二致(不完全是),它的性能和稳定性也能马上得到保证,这比从头构建一个新平台成本低得多。

    构建于 JVM 之上,Clojure 就是一门严肃的语言,而非很多人眼中的 LISP家族中的 玩具语言,你学习后可以马上使用并且实践。但是 Clojure 又是 LISP 方言,LISP 的神奇能力它还都保留,这样兼具美学和实用的语言如何让人不爱?我相信很多熟悉 Scheme 之类方言的童鞋,并且有 Java 背景的,都会对 Clojure 有相见恨晚的感觉。

    设计原则

    Clojure 的设计原则可以概括成 5 个词汇:简单、专注、实用、一致和清晰。这不是我概括的,而是《The joy of clojure》概括的。

    • 简单: 鼓励纯函数,极简的语法(少数 special form),个人也认为 clojure 不能算是多范式的语言(有部分 OO 特性),为了支持多范式引入的复杂度,我们在 C++ 和 Scala 身上都看到了。
    • 专注:前缀运算符不需要去考虑优先级,也没有什么菱形继承的问题,动态类型系统(有利有弊),REPL 提供的探索式编程方法(告别修改 / 编译 / 运行的死循环,所见即所得)。

    • 实用:前面提到,构建在 JVM 之上,跟 Java 语言的互操作非常容易。直接调用 Java 方法,不去发明一套新的调用语法,努力规避 Java 语言中繁琐的地方 (doto, 箭头宏等等)。

    • 清晰:纯函数(前面提到),immutable var,immutable 数据结构,STM 避免锁问题。不可变减少了心智的负担,降低了多线程编程的难度,纯函数也更利于测试和调试。

    • 一致:语法的一致性:例如 doseq 和 for 宏类似,都支持 destructring, 支持相同的 guard 语句(when,while)。数据结构的一致性:sequence 抽象之上的各种高阶函数。

    • 具体到 STM,我个人认为这个特性在日常编程中,其实你用到的机会不多。在 web 编程里,你的并发模型 Web Container 已经帮你处理(tomcat,jetty),事务也是数据库帮你处理,几乎找不到场合去使用 STM。这个特性在做一些中间件或者底层 framework 的时候才可能用到。这个特性的设计上面已经提到,跟 clojure 的设计目标是紧密相关的,跟 immutable 数据结构也是密不可分,同时它也不是没有代价,事务历史记录和慢事务频繁回滚的代价,有时候你还是需要退回去使用 Java 那套锁机制,庆幸的是 Clojure 不阻止你去使用,并且提供了类似 locking 这样的宏来方便你使用。

    缺陷

    Clojure 的设计缺陷不能说是缺陷,这是由于它设计的目标决定的,有得必有失。

    • 首先还是 JVM,基于 JVM 有种种好处,但是 JVM 的启动速度实在悲剧,因此用 Clojure 写一些小的 script 处理日常事务,显得还是不够得心应手,这样的工作我还是用 Ruby,Python 的脚本语言来搞定更便捷。不过目前 Clojure 有一些其他语言之上的实现,比如 clojure-pyjoxaclojureclr 这些实现应该会比 JVM 的启动快很多(抱歉,我没测试过)。

    • 不仅如此,因为 Clojure 跟 JVM 平台的绑定如此之深,并且为了真正发挥 Clojure 的威力,你还需要去熟悉 Java 平台的东西,熟悉 Java 语言、类库、内存模型、GC 优化、多线程和网络编程、开源类库等等。可以这样认为:想成为一个好的 Clojure 程序员,首先需要是一名好的 Java 程序员。这也一定程度上阻碍了 Clojure 的推广,提高了学习成本。

    • 其次,Clojure 的 API 设计上,有时候不符合你的直觉,而是符合 Clojure 的哲学,比如 contains?函数对 vector 等数组型集合的调用上。关于这一点,Rich 的回答是Elegance and familiarity are orthogonal.,也就是优雅和熟悉是正交关系的。保持 API 内在的一致性,比直觉的熟悉更重要,这是更深入思考、理性的直觉。

    • 第三,弱类型的好处足够多,灵活,减少声明代码,适合探索式编程;同样,坏处也不是没有,没有类型保障,错误可能要等到运行时才能发现,静态代码检查工具也没有办法帮你发现,这就需要你一定程度的测试代码来保证运行时行为。

    • 第四,性能上,虽然 clojure 生成的字节码已经很高效,也有 type hint 这样的技术来帮助提升性能,但是会有不少的转型 (checkcast)、装箱和拆箱(boxing and unboxing)以及类型判断分支跳转的多余指令,这在一些性能敏感的应用里可能会暴露出来。尽管我认为大多数网站型的应用瓶颈都会落在 IO 上。

    总之, Clojure 是一门精心设计的、完全融入作者对编程的思考的、富有生产力的现代编程语言,值得每个对生产效率、函数式编程、并发编程有兴趣的朋友深入了解下。

    作者:Dennis Zhuang LeanCloud Tech Leader

    备注:LeanCloud 采用了多种语言混合来构建整个后端系统,包括 Clojure、Java、Node.js、Scala 等。其中 Clojure 构建了整个网站门户、存储开放 API、推送、聊天等核心服务,Node.js构建了云端代码服务(类似应用代码托管),我们还使用 Scala 编写的 Spark 任务来处理离线数据分析,此外,还有大量的统计类 MapReduce 任务使用 Java 编写并运行在 Hadoop 集群上。不同服务之间使用 RESTful 协议、RPC 框架或者队列进行通信。

    4 条回复    2021-01-04 09:52:49 +08:00
    faywong8888
        1
    faywong8888  
       2018-04-15 22:30:13 +08:00
    +1
    ZoomQuiet
        2
    ZoomQuiet  
       2018-07-22 20:30:24 +08:00
    是也乎,( ̄ ̄)

    简单的说, 只有 资深的 JAVA 工程师, 才能真正用起来 Clojure
    Subfire
        3
    Subfire  
       2019-12-23 20:21:14 +08:00
    boss 直聘一搜 Clojure, 缪缪不到 1 页, 搜 Golang 等, 几千页...
    AndyAO
        4
    AndyAO  
       2021-01-04 09:52:49 +08:00
    @Subfire #3
    想到两本书上对类似现象有意思的描述

    ...

    举例来说,假设你需要写一个软件。你的经理根本不懂这个软件的运作机制,也不知道各种编程语言有什么区别。但是,他竟然明确要求你一定要使用某一种语言进行开发。没错,他就是要求你一定要用 Java 语言。

    为什么他会提出这种要求?让我们看看他脑袋里是怎么想的。他的想法无非就是,Java 是业界的标准。我知道肯定如此,因为媒体对此有铺天盖地的报道。既然它是标准,那么使用它就不会错。另外,这也意味着人才市场上肯定有无数 Java 程序员,即使现在为我打工的这批人都辞职了(真奇怪,这种事情总是不断发生),我也能够轻易地找到替代者。
    嗯,这听起来也不无道理。但是,它的前提是一个没有说出口的假设,而这个假设实际上是错的。你的经理相信所有编程语言的功能都差不多,可以互相替代。如果这种想法是对的,那么他要求你用 Java 编程就很合理了。反正编程语言之间没有区别,那么就用大家都在用的那种语言吧。

    但是,编程语言是不一样的。就算不探讨各种语言之间的具体区别,我也能向你证明这一点。回到 1992 年,如果你问经理使用什么语言开发软件。他会像今天一样毫不迟疑地回答说 C++。如果所有编程语言都一样,为什么答案变了?进一步说,为什么 Java 语言的设计者要如此麻烦地去创造一种新语言呢?

    一般来说,如果你动手创造一种新语言,那是因为你觉得它在某些方面会优于现有的语言。

    ...

    From:Hackers & Painters


    ...

    首当其冲的是,亚马逊的主流语言里有两门非常嗦的语言 C++和 Java,外加门精练的语言 Perl 。但是 Perl 正受到排挤,渐渐退出主流。我觉得这是因为 Perl 程序员能用更少的人力完成和 Java/C++程序员同样的工作量,所以要是比人多的话,他们注定是赢不了的。根据我们的估算,亚马逊的代码量比它的功能数量膨胀得更快。

    ...

    From:A Programmer's Rantings
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     4708 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 04:00 PVG 12:00 LAX 20:00 JFK 23:00
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86