Clojure是一门Lisp方言——确切地说,是一门JVM上的Lisp方言——也是一门非纯粹的函数式语言。

Clojure理所当然地秉承了Lisp“代码即数据( code is data! )”的设计哲学, 代码和值一样处于同等地位。

这一著名特性,内含了无穷无尽魔法威力,并通过括号体现出强大的语言表现能力。

但是也正是因为这个,该特性正是让无数熟谙其它语言模式的开发者难以跨越的一道门槛。

本文希望通过解读来帮助大家更好的理解和使用这个特性。

一、表达式

首先我们来说下表达式的概念 。

在clojure中,代码就是由表达式组成的,每个表示每个表达式都会产生一个值。

常见的表达式如:

60

[2  4  6]

(+ 1 2)

(average [2 3 4])

1)上面的第一个表达式就是一个字面常量,这里是一个整数。

2)第二个是个整数序列。

3)第3和4 都是函数调用,Clojure中,小括号 () 表示函数调用,括号中的第一个值是函数名,剩下的值是参数,整个调用表达式被求值的结果作为调用的返回值。

在Clojure中,类似其它语言的运算符,都可以看做是函数,这也为何上面例子中的 (+ 1 2) 这个表达式中 + 号放在前面的原因。

二、函数

函数定义本身也是一个表达式,调用宏defn定义,也是放到 () 中,其函数体也是由1个或多个表达式组成。

语法: (defn 函数名 [参数列表] 表达式1  表达式2 .... 表达式n)

上面定义返回的是一个函数。

函数调用

语法: (函数名 表达式1  表达式2 .... 表达式n)

上面的表达式就是传递给函数的参数值。

在Clojure中,函数既可以直接被调用,用()调用。 也可以作为参数传递给函数,也可以作为函数执行的返回值。

例1:

user=> (defn hello[] 10)
#'user/hello
user=> (hello)
10

例2:

user=> (defn hello[a b] (+ a b))
#'user/hello
user=> (hello 3 4)
7

例3:

user=> (defn hello[a b] (+ a b) (* a b) )
#'user/hello
user=> (hello 2 4)
8

例4:

user=> (defn hello[a b] (* (+ a b) (- a b)) )
#'user/hello
user=> (hello 5 3)
16

三、匿名函数

Clojure中,强调“代码即数据”,这也意味者代码(即函数)可以像数据一样随意的被传递、返回等。

如果每次都需要显示的去定义一个函数,特别是对一些一次性操作,会很麻烦,也会增加代码的复杂性,不简介,还可能会导致命名冲突与覆盖,留下隐患。

很多场景下,其实只需要函数体和参数,对函数的名称不关心。这时就可以通过匿名函数来实现。

定义匿名函数的语法是:#(表达式)

传入的参数用 % 占位符来标记。

其中%表示唯一的参数;%1、%2 ..依次表示第1、2、..个参数;%&表示所有参数

例1:

user=> (defn hello[para value] (para value))
#'user/hello
user=> (hello #(print %) 10)
10nil

上面第一句代码中para参数是一个函数,第二句 #(print %) 定义了一个匿名函数并传给hello方法。

例:2

user=>  (defn hello[para value1 value2] (para value1 value2))
#'user/hello
user=> (hello #(* %1 %2) 2 3)
6

user=> (hello #(println %&) 2 3)
(2 3)

例3:

user=> (#(+ %1 %2) 10 20)
30

上面的语句与如下语句效果一样

user=> ((defn fun[a b] (+ a b)) 10 20)
30

只不过上面这个语句定义的是个有名额函数,函数名为fun。

除了在定义时被使用外,后续还能继续通过名称被调用

user=> (fun 2 8)
10

总结一下,clojure代码就是由 很多的 () 函数调用(嵌套)完成。注意几个语法的区别:

() 这个是函数调用,第一个值是函数名,后续值是参数。 返回的是函数执行的结果。

'() 是 列表,括号中是空格分隔的表达式。返回的是列表对象。

#() 是匿名函数,返回的是一个函数。注意是函数,不是函数调用。

最新文章

  1. centos 安装php7.0.2
  2. Java解析HTML之HTMLParser使用与详解
  3. Android 热补丁和热修复
  4. zk listbox 点击列标题实现排序功能
  5. mongo自带测试
  6. oc中对象的初始化
  7. 【原】 Spark中Worker源码分析(二)
  8. JS日历控件
  9. (转)eclipse自动补全的设置
  10. HDU 5826 physics
  11. Texlive + TexStudio + Language Tool Win7配置
  12. 爬虫(scrapy第一篇)
  13. dataTable 实战总结
  14. jQuery效果------隐藏hide()/显示show()
  15. Java 中的悲观锁和乐观锁的实现
  16. python 中的 list dict 与 set 的关系
  17. jscript DOM操作
  18. unity3d-游戏实战突出重围,第四天 添加角色
  19. Vitrualbox 桥接网卡界面名称未指定、Filters currently installed on the system have reached the limit、不能为虚拟电脑 打开一个新任务
  20. Replication监控及自动故障切换

热门文章

  1. 国内外主流BI厂商对比
  2. nodejs的npm安装模块时候报错:npm ERR! Error: CERT_NOT_YET_VALID的解决方法 - 包子博客 _ 关注互联网前端、开发、SEO、移动互联网应用技术
  3. Spring Boot使用Druid和监控配置
  4. Nginx CORS实现JS跨域
  5. STL deque详解
  6. hdoj 2222 Keywords Search(AC自动机)
  7. lua的前景??
  8. UISegmentedControl(分页控制器) AND UISlider(滑块控制器)
  9. [译]SSRS 报表版本控制
  10. RSA, ACS5.X 集成配置