Clojure 快速突击(续)

Clojure 确实要比 Python 语义上庞大, 所以无法尽量在一篇之中收纳进来, 只得另立新篇, 也许还会有第三篇笔记. 现在开始学习函数定义

函数定义

函数用  defn 宏来定义, 函数名与参数列表之间可选的字符串是函数的注释, 相当于 Python 的函数体中第一个字符串,  这个字符串能被 (doc func-name)  列出来, Python 中是用 dir(fun_name 显示函数帮助. 不需要 return 关键字, 和 Groovy/Scala 一样最后一个表达式的值为函数的返回值, 所以函数总是有返回值(或为 nil).

和 C 语言一样, 函数必须先定义再使用, 否则要用 (declare function-names) 提前声明, 下面代码是在 Clojure 的 REPL 中执行的

提一下 Clojure 的命名规则, 变量和函数名用中划线连接的小写单词. defn- 定义的函数是私有, 只对当前名字空间可见, 比如上面的  user 名字空间. 有点像 Python 的下划线变量或函数的可见性约定.

Clojure 支持可变函数(VarArgs), & 之后的参数在一个 list 中, 如

函数可包含多个参数及对应的方法体, 以此来实现默认参数或重载

匿名函数已在第一篇中讲过了, 它其实就是一个 Lambda 表达式了, #(...), 参数直接用 %(%1), %2, %3 .... 了. Clojure 的这种方式的匿名函数还是很方便的.

comp 可以把多个函数以管道形式组合起来, 如

complement 接受函数为参数求补, partial 给旧的函数制定一个初始值. 

与 Ruby  的约定一样, Clojure 定义谓词型的函数使用问号, 像

学习 Clojure 到现在基本能够体会到它的代码就是数据, 代码中常用的 () 和 [] 怎么变都是 List 和 Vector 的组合, 再多就是把 List 和 Map 加进去. 数据结构就是编程, 谁想到 Lisp 这么一种语言真是太有才了.

发现一个有意思的事情, 下面的代码因为输入有误, 结果是 Cloujure 把结果都算出来了, 再告诉我最后多了一个括号, 可见它的执行机制是能匹配到括号就能行, 多了也不是大事. 可以试下 (def v 123))))))) 再多的括号都能为你把变量 v = 123 正确的定义出来.

Java 互操作

Clojure 使用 Java 的东西可没有 Scala 那么简单, 主要了解几个宏 import, ., .., .?., 以及 doto 函数. Clojure 为同一个操作准备了多种方式, 看似灵活, 其实让人更凌乱. 使用 (doc import), (doc doto) 这样来查看使用方法. 大概用代码罗列一下:

真正要使用的时候再回过头来看吧, 主要有两点比较新颖: 1) .. 能把方法串接起来 2) doto 可用来调用一个对象的多个方法, 方法不要求 return this 也能链接:

所有的  Clojure 方法都实现了 java.lang.Runnable 接口. Clojure 的异常都是运行时异常. 如果要捕获从 Java 代码抛出的检测异常需要用到 try, catch, finally, 和  throw 那些被称作 special forms 的东西.

流程控制

条件处理, special form if, 宏 when, when-not, 能绑定 binding 变量的宏 if-let 和 when-let, 还有相当于 switch/case 语句的 condp 和 cond 两个宏.do 可以用来包裹多个操作, 方便在单个条件中执行多条语句. 和 Scala 一样, Clojure 的条件语句是有返回值的. 下面一起进到代码里去理解

condp 和 cond 匹配不到条件就会抛出 IllegalArgumentException, 每个分支自带 break 功能.

循环, 用宏 dotimes 和 while

for, doseq 和 special form loop, 它们可以用 :when 或 :while 进行过滤, 例子:

Clojure 的循环与 Java 的  foreach 写法有点类似.

往下是递归, Clojure 和 Java 一样也是不支持尾递归优化的, loop/recur 组合可把一个看似递归的调用变成一个迭代, 这是做了尾递归优化该做的事情了.

已经不想再往下写了, 先了解这些 Clojure 的基础知识了, 剩下的还有一本 "Clojure IN ACTION" 这本书要细细的品读了.

 

本文链接 https://yanbin.blog/clojure-get-started-1/, 来自 隔叶黄莺 Yanbin Blog

[版权声明] Creative Commons License 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。

Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments