Programming Clojure学习笔记——函数编程

来源:互联网 发布:tags是什么软件 编辑:程序博客网 时间:2024/05/17 02:31
5.1 函数编程概念
1. 纯函数
函数式程序由纯函数构成。纯函数没有副作用,它只依赖与函数参数,只能通过函数返回值影响函数外部。
纯函数常常与不可变数据一起工作。如:
(defn mystery [input]
    (if input data-1 data-2))
如果data-1和data-2是可变的,则它们可能被外界改变,对相同的input参数,可能输出不同,这与纯函数的特性不符。

2.持久化数据结构
所有Clojure数据结构都是持久的,即Clojure数据结构保持原版数据的同时最大程度与新版本的数据共享结构。
如给列表a
(def a ’(1 2))
添加元素0,得到列表b
(def b (cons 0 a))
此时列表a没有改变,列表b由元素0和a的元素组成,并没有再重复构建元素1和2,及b直接共享a的元素。

3.延迟(Laziness)和递归(Recursion)
函数编程大量使用递归和延迟。
递归:一个函数直接或间接地调用自己;
延迟:一个表达式的值直到真正使用时才计算。计算延迟表达式的值称为实现表达式。

Clojure中,函数和表达式都不是延迟的,但序列通常都是延迟的。

4.引用透明(Referential Transparency)
延迟依赖一种特性,这种特性是在任何时候都可以直接将函数调用替换为函数返回值。拥有这种特性的函数被认为是引用透明的,因为注意的函数调用可以被替换但不影响程序的行为。
引用透明受益于:
(1) 缓存,自动缓存函数结果
(2) 自动并行移动函数结果到其他进程或机器

所有的纯函数都是引用透明的。

5. 函数编程(FP)的好处
(1) 易于阅读和编写,因为函数只与输入参数有关
(2) 提高复用
(3) 可组织,纯函数是真正封装的和可组织的

6. 六个原则
Clojure中函数编程有六个原则:
(1) 避免直接递归
(2) 使用recur生成标量值或小的固定序列
(3) 生成大的可变序列一定要延迟
(4) 只实现延迟序列中需要的那一部分数据
(5) 使用序列库,避免直接使用recur和延迟相关API
(6) 细分
这六条原则都是指导性的,并不是绝对的。只要有足够的理由就可以不遵守它们。