ReactWheels01_01函数式编程

Lisp

  1. Lisp是函数式的正宗,而React抄袭了函数式,我们应该学习正宗的,追根溯源
  2. 你的知识范围应该大于 工作需要用到的知识,这样才能游刃有余
  3. 推荐书籍 SICP

lisp 基本语法

表达式(算术运算)

1
2
3
4
5
6
7
8
9
10
11
# 1 + 2
> (+ 1 2)
< 3

# 1 + 2 + 3 + 4
> (+ 1 2 3 4)
< 10

# 3*3 + 4*4
> (+ (* 3 3) (* 4 4))
< 25

较长的表达式(组合的表达式)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(+ (+ 3 (+ (* 2 4) (+ 3 5))) (+ (- 10 7) 6))

// 表达式复杂建议换行
(+
(+
3 (+
(* 2 4)
(+ 3 5)
)
)

(+
(- 10 7)
6
)
)

命名 (定义,不叫赋值)

1
2
3
4
< (define size 5)
>
< (* size 2)
> 10

复杂过程(函数定义)

1
2
3
4
5
6
7
8
# 也是要 define声明 第一个括号(函数名 参数1,参数2) 第二个括号(函数的实现)
< (define (add a b) (+ a b))
< (add 1 2)
> 3

< (define (square x) (* x x))
< (square 4)
> 16

递归求值

1
2
3
4
5
6
7
8
9
10
(+
(*
2
(+ 7 8)
)
(+
3
(- 10 6)
)
)

带入求值

1
2
3
4
5
6
7
8
9
10
11
12
(define (sq x) (* x x))
(defined
(sqsum a b)
(+ (sq a)
(sq b)
)
)
)

(define (f z)
(sqsum z (+ z 1))
)

注意:

  1. 代码只是为了方便我们理解函数,并不一定是实际的工作原理
  2. 不是所有代码都能代入的,必须满足一定的条件

if

求绝对值的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(define (abc a)
(if (> a 0)
a
(-a)
)
)

// (if arg1 arg2 arg3)
/*
arg1 条件
arg2 真
arg2 假

注意:为什么没有return ,不是所有语言都需要return
if是默认返回的
*/

递归

  • 阶乘

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    f(n) = n!

    f(1) = 1
    f(2) = 1 * 2
    f(3) = 1 * 2 * 3
    f(n) = 1 * 2 * 3 ... * (n-1) * n

    演变一下

    f(1) = 1
    f(2) = f(1) * 2
    f(3) = f(2) * 3
    f(n) = f(n-1) * n
  • lisp 的形式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    (define (f n)
    (if (= n 1)
    1
    (*
    n
    (f (- n 1))
    )
    )
    )

    // 此时我想问 f(6) 的结果是什么
    f(6)
    (* 6 f(5))
    (* 6 (* 5 f(4)))
    (* 6 (* 5 (* 4 f(3)))
    (* 6 (* 5 (* 4 (* 3 f(2)))
    (* 6 (* 5 (* 4 (* 3 (* 2 f(1)))
    (* 6 (* 5 (* 4 (* 3 (* 2 1))
    (* 6 (* 5 (* 4 (* 3 2))))
    (* 6 (* 5 (* 4 6)))
    (* 6 (* 5 24))
    (* 6 120)
    720

    // 这就是 递归

迭代

之前我们求阶乘咋求的 从后往前 f(6) > 6 * f(5)

  • 我们正着想呢?
1
2
3
4
5
6
7
8
9
10
11
12
6!  ?

1!
2!
3!
4!
5!
6!

// 伪代码
result = n * result
n = n + 1

伪代码(迭代过程)

1
2
3
4
5
6
7
8
9
10
11
12
13
(f 6)
(j result n n-max)
// 第一个参数是 结果
// 第二个参数是 当前的 n
// 第三个参数是 结束条件

(j 1 1 6)
(j 2 2 6)
(j 6 3 6)
(j 24 4 6)
(j 120 5 6)
(j 720 6 6) // 还要再循环一次 因为不知道该不该结束
(j ? 7 6) // 7 > 6 返回到 f(6)

lisp 代码

1
2
3
4
5
6
7
8
9
10
11
(define (fac n)
(fact-iter 1 1 n))
(define (fact-iter result max-n)
(if (> n max-n)
result
(fact-iter (* n result)
(+ n 1)
max-n
)
)
)
  • 递归:先递进(展开),在回归(求值)
  • 迭代:从一个状态到下一个状态(状态便明亮的数目固定)

高阶函数

有空在完善lisp代码吧。。。

  • 接受一个或多个函数当作参数
  • 输出一个函数

总结

  1. 代入法求值
  2. 递归与迭代的区别
  3. 高阶函数