Clojure,这是什么鬼?一门基于JVM(现在也有基于.NET CLR的了:Clojure CLR) 的函数式编程语言。在JVM平台运行的时候,会被编译为JVM的字节码进行运算。。为什么要学它?其设计思想独特。有何先进独特之处?后面我会讲。

说实话,现在编程语言满天飞,哥也只是玩过C/C++/Basic/C#/javascript/Java/Python,,哥最喜欢的语言么?看平台了。Windows是C#,跨平台Java,脚本Python。其它的,比如: “最纯的函数式语言”Haskell、“天生擅长高并发的”Erlang,“当红辣子鸡的并发语言”Go,“上手最快的高并发语言”Node,“简约而不简单”的Scala.....,这些都是很棒的语言。哥今天来学一门独特的语言Clojure,首先因为它是LISP —— 一门富有传奇色彩的语言,其次,它小巧、简洁、稳定,是非常酷的语言,既继承了lisp的优美,也保留了java的实效,还具有高并发的特性。而且有个有名的应用实例,那就是Twitter Storm流式计算框架——开源实时Hadoop,是用Clojure语言写的。拿来玩玩,不选它选谁呢?

环境安装

哥今天是在一台win7的笔记本上来安装的(mac的兄弟此处可以鄙视我~),首先机器要安装好JDK7和maven并已配置好环境变量,然后Google搜索“clojure install”,下载与安装leiningen(这是什么鬼?Clojure的项目构建工具,可以自动给你搞定clojure项目打包依赖),设置环境变量,最后是安装IDE插件,例如:Emacs、Eclipse(至少Kepler)。OK,搞定!

使用 immutable 数据

这是Clojure在理念上与我们平常的Java或c#最大的区别,即使用不可改变的值,这儿的值可以是数字、字符串、向量、映射或集合。一旦创建,值不可改变。Clojure不是让“内存变量”的内容可变,而是让符号绑定到不同的不可变值上。

例如:( def hello ( fn [] "Hello, world!" ) )

这段Clojure代码把标识符hello绑定了一个值,这个值是一个函数(函数式编程意味着函数是一个值): (fn [] "Hello, world!"),不带参数,输出"Hello, workld!"。我们运行一下:(hello),输出Hello, workld!

现在我们让它重新绑定另外一个值:( defn hello ( fn [] "Get shit done!" ) )

这段Clojure代码把标识符hello绑定了另外一个值,这个值是一个函数: (fn [] "Get shit donw!"),不带参数,输出"Get shit done!"。

注意:与java等的变量赋值相比,区别是一个是变量内容变了,一个是值一旦创建,不可改变,符号重新绑定是指在不同时期指向不同的值。

使用 immutable 数据的好处是什么?区分identity和value,value不可变,给identity赋值新的value时都要经过语言内制定的function,由语言来保证一致性,让编写并发程序变得容易。这个并发的特性后面会讲到。

闭包(closure)

闭包是函数式编程中非常重要的特性,Clojure的闭包很类似javascript的闭包,举个栗子:

(defn double-op

  [f]

  (fn [& args]

    (* 2 ( apply f args ))) )

(def double-add (double-op +))

上面代码的详细解释:第一行定义一个名为“double-op”函数,这个函数用一个形参f。这个形参f应该是一个函数,因为我们的函数体是一个用fn(fn是一个宏,可以理解为宏也是一种能够动态生成函数的方式,且功能上强大很多)定义的匿名函数。这个匿名函数可以接受一或者多个参数(形参名字args前的“&”表明了这一点)。这个匿名函数会通过传入的实参(也就是f的值)而完整化,并作为函数“double-op”的返回值。函数apply会将第一个实参(一般为一个函数)作用于其余的实参之上,也就是说调用第一个实参代表的函数,并将其余的实参作为其参数传入。使用apply的好处在于不必立刻在代码中填入传入“其余的实参”,而可以用引用名代替。这时,这些“其余的实参”可以被叫做预参数。倒数第二行代码定义了一个名为“double-add”的引用,这个引用返回一个函数。这个返回的函数是通过向函数“double-op”传入函数“+”而完整化后得出的。换句话说,我们在这里定义了一个名为“double-add”的函数。调用方法是:(double-add 5 6),输出 22(把所有“其余的参数”相加并乘以2)。

并发(Concurrency)

 

Java的状态模型从根本上来说是基于状态可变思想的,这直接导致并发代码的安全问题,所以OOP的java的并发编程非常复杂,只能靠悲观锁(locking),或CAS来解决。当然,OOP的真正优势在于对现实世界的建模,而不是数据处理。我们应该辩证的看待不同范式的编程语言,死磕一个必然会使思想禁锢,甚至编程灵感尽失。回到正题,Clojure的指导思想是把线程彼此隔开来实现线程安全,开发人员不用care线程调度,让Clojure来管理线程池。假设“没有共享资源”的基线和采用不可变值使Clojure避开了很多Java面临的问题。举例来说,Clojure的Ref并发模型使用STM机制,该模型在符号和值之间引入了一个额外的中间层,符号绑定到值的引用上,而不是直接绑定到值上,这个系统是事务化的,由Clojure运行时来进行协调,开发人员无需担忧任何锁问题。

STM机制比较抽象,举个栗子吧:银行转账的时候,客户的银行余额显然应该是可变的,而且肯定会有多个线程会对这个余额进行读写,Clojure对于这种情况提供了软件事务内存(Software Transactional Memory -- STM),STM的作用简单点说就是我们无法直接对状态进行读写, STM代理了我们对于状态的所有读写,当我们说要一个状态进行修改的时候,STM充当了余额状态与值的中间层 -- 也就是说多线程之间的协调由STM帮我们搞定了,自然不会有问题了。

以上是对STM的粗略解释,要深入研究建议去阅读R. Mark Volkmann的论文《Software Transactional Memory》。

下面是使用ref的一段代码,不解释了,自己去玩吧:

(import ' (java.util.concurrent Executors) )

;;(test-stm 10 10 10000)

;;-> (550000 550000 550000 550000 550000 550000 550000 550000 550000 550000)

(defn test-stm [nitems nthreads niters]

  (let [refs (map ref ( repeat nitems 0 ))

    pool (Executors/newFixedThreadPool nthreads )

      tasks (map (fn [t]

      (fn []

        (dotimes [n niters]

          (dosync

            (doseq [r refs]

              (alter r + 1 t ))) )))

      (range nthreads ))]

  (doseq [future (.invokeAll pool tasks)]

    (.get future) )  

  (.shutdown pool)

(map deref refs)) )

可以看到比起冗长的Java,Clojure的语法非常简练,封装的很好,既继承了lisp的优美,也保留了java的实效,还具有高并发的特性。

CPU/网络I/O高并发

 

现在所谓的“高并发”很多是指网络I/O高并发,具体来说指的是单进程接受多少多少个连接,例如:Node.JS实现了这个,可以用很少的资源吃满I/O,这里的资源的重点自然是指内存和CPU。而Clojure的高并发完全不是指的这个,Clojure的STM高并发指的是CPU密集型的高并发,不是网络I/O, 这点不要搞错了。其网络I/O高并发完全依赖JVM,或是其他的NIO框架比如Netty或Mina什么的,所以Clojure 提供了相对更为正交的功能集合(STM,并发支持,独立的异步 I/O 库)

原文:Clojure上手

原文发布与微信公众号 rayisthinking

Clojure上手的更多相关文章

  1. 我的Emacs折腾经验谈(二) Emacs上手难的原因

    既然之前说过要写我怎么继续折腾Emacs的,过了一个星期这里就是第二篇了,突然觉得我把blog这样分节不是很好,每次可能要凑一些东西才有该有的篇幅,而且说的东西可能东一点西一点,这样一篇看下来不利于检 ...

  2. Clojure基础课程2-Clojure中的数据长啥样?

    本文来自网易云社区 作者:李诺 " Clojure is elegant and pragmatic; it helps me focus more on solving business ...

  3. JavaScript之父Brendan Eich,Clojure 创建者Rich Hickey,Python创建者Van Rossum等编程大牛对程序员的职业建议

    软件开发是现时很火的职业.据美国劳动局发布的一项统计数据显示,从2014年至2024年,美国就业市场对开发人员的需求量将增长17%,而这个增长率比起所有职业的平均需求量高出了7%.很多人年轻人会选择编 ...

  4. 【Python五篇慢慢弹】快速上手学python

    快速上手学python 作者:白宁超 2016年10月4日19:59:39 摘要:python语言俨然不算新技术,七八年前甚至更早已有很多人研习,只是没有现在流行罢了.之所以当下如此盛行,我想肯定是多 ...

  5. Impress.js上手 - 抛开PPT、制作Web 3D幻灯片放映

    前言: 如果你已经厌倦了使用PPT设置路径.设置时间.设置动画方式来制作动画特效.那么Impress.js将是你一个非常好的选择. 用它制作的PPT将更加直观.效果也是嗷嗷美观的. 当然,如果用它来装 ...

  6. ECharts数据图表系统? 5分钟上手!

    目录: 前言 简介 方法一:模块化单文件引入(推荐) 方法二:标签式单文件引入 [前言] 最近在捣鼓各种插件各种框架,发现这个ECharts还是比较不错的,文档也挺全的,还是中文的,给大家推荐一下. ...

  7. 快速上手Unity原生Json库

    现在新版的Unity(印象中是从5.3开始)已经提供了原生的Json库,以前一直使用LitJson,研究了一下Unity用的JsonUtility工具类的使用,发现使用还挺方便的,所以打算把项目中的J ...

  8. Masonry介绍与使用实践:快速上手Autolayout

    1 MagicNumber -> autoresizingMask -> autolayout 以上是纯手写代码所经历的关于页面布局的三个时期 在iphone1-iphone3gs时代 w ...

  9. [译]:Xamarin.Android开发入门——Hello,Android Multiscreen快速上手

    原文链接:Hello, Android Multiscreen Quickstart. 译文链接:Hello,Android Multiscreen快速上手 本部分介绍利用Xamarin.Androi ...

随机推荐

  1. sql server 2000通过机器名可以连,通过ip连不上的问题

    客户那边两台服务器A和B,之前一直都是好好的,今天因为换了网络环境,结果数据库之间不能相互访问了. 目前只能A访问B,B访问不了A,在服务器A上面试了,通过ip连本机,也是连接超时. 开始想着是服务器 ...

  2. Sql Server 孤立用户解决办法

    Sql Server 孤立用户 是我们经常遇到的事情,今天详细的梳理了下,希望能帮到你 当把用户数据库从一台 Sql Server 使用备份和恢复的方式迁移到另一台服务器.数据库恢复以后,原先用户定义 ...

  3. python 内置函数 map filter reduce lambda

    map(函数名,可遍历迭代的对象) # 列组元素全加 10 # map(需要做什么的函数,遍历迭代对象)函数 map()遍历序列得到一个列表,列表的序号和个数和原来一样 l = [2,3,4,5,6, ...

  4. textarea 在不同浏览器高宽不一致的兼容性问题

    在html,很多同学喜欢使用rows.cols,来设置textarea的高宽,却发现,在火狐跟其他浏览器,好像高宽却不一致! 因为这是火狐的一个bug, https://bugzilla.mozill ...

  5. OpenWRT连接OPENVPN的教程

    这是相当基本没有任何web界面,只是几个命令如何运行OpenWRT的 OpenVPN的例子. OpenWRT的设置更复杂,所以这个教程仅供爱好者和经验的用户使用参考. 本教程假定您有OpenWRT的安 ...

  6. stringbuffer与stringbuilder与String

    1. 在执行速度方面的比较:StringBuilder > StringBuffer 2. StringBuffer与StringBuilder,他们是字符串变量,是可改变的对象,每当我们用它们 ...

  7. 关于QT安装的一些心得(QT551, VS2013)项目开发配置,以及项目结构分析

    推荐QT开发的配置如下: 我的硬件配饰中等,所以推荐一下配置: QT551版本,目前QT最新版8.0,为了稳定选择551版本 VS2013IDE, 因为VS2010与VS2013的编译器相同,但是VS ...

  8. 对象池与.net—从一个内存池实现说起

    本来想写篇关于System.Collections.Immutable中提供的ImmutableList里一些实现细节来着,结果一时想不起来源码在哪里--为什么会变成这样呢--第一次有了想写分析的源码 ...

  9. CSS的四种引入方式

    1.使用link标签引入css文件: <head> <link rel="stylesheet" type="text/css" href=& ...

  10. SQLSERVER监控复制并使用数据库邮件功能发告警邮件

    SQLSERVER监控复制并使用数据库邮件功能发告警邮件 最近熬出病来了,都说IT行业伤不起,不说了,说回今天的正题 正题 上个月月底的时候因为要搬迁机房,需要将一个数据信息数据库先搬到我们的机房,然 ...