Slide 1

Slide 1 text

FRP & RAC 冰霜

Slide 2

Slide 2 text

什么是函数响应式?

Slide 3

Slide 3 text

命令式 VS 函数式 int factorial(int x){ if (x < 0) return INT_MIN; int result = 1; for (int i = 1; i <= x ; ++i) { result *= i; } return result; } 1. 如何计算 2. 表达式和语句 3. 状态量 函数式编程⾥⾯是基本上没有状态量,只有表达式,也没有赋值语句。利⽤了递归解决了问题。 int factorial(int x){ if (x < 0) return INT_MIN; if (x==1) return 1; return x * factorial(x-1); }

Slide 4

Slide 4 text

命令式 VS 响应式 09:30 Magna Amet 05:20 AM 09:45 PM Euismod, Ipsum void react() { int a = 8; int b = 9; int c = a + b; a = 10; NSLog(@"%d", c); } 在⾯向对象语⾔中也是可以实现响应式编程的,具体做法应该是,把关系抽象出来,然后把 变化抽象出来,⽤关系把变化事件传递下去。Cocoa框架下RAC的实现就是如此。

Slide 5

Slide 5 text

Cum sociis natoque penatibus et magnis parturient montes. 在计算机编程中,假如满⾜下⾯这两 个句⼦的约束,⼀个函数可能被描述 为⼀个纯函数: 1. 给出同样的参数值,该函数总是 求出同样的结果。该函数结果值不 依赖任何隐藏信息或程序执⾏处理 可能改变的状态或在程序的两个不 同的执⾏,也不能依赖来⾃I/O装置 的任何外部的输⼊(通常是这样的 --看下⾯的描述)。 2. 结果的求值不会促使任何可语义 上可观察的副作⽤或输出,例如易 变对象的变化或输出到I/O装置。 纯函数 函数的返回值是不需要依赖所有(或任 何)参数值,必须不依赖参数值以外的 东⻄。函数可能返回多重结果值,并且 对于被认为是纯函数的函数,这些条件 必须应⽤到所有返回值。假如⼀个参数通 过引⽤调⽤,任何内部参数变化将改变函 数外部的输⼊参数值,它将使函数变为⾮ 纯函数。 ⼀个纯函数在执⾏的过程中,只跟 ⼊参有关,在函数体中并不会引⽤ 外部全局变量,或者说是⼀个类⽅ 法⾥⾯的其他成员变量。另外,纯 函数除了返回值之外,也不会去改 变外部的变量值。满⾜上⾯这两点 的纯函数,就可以说它是引⽤透明 的。也有说法叫这种特性为幂等性

Slide 6

Slide 6 text

副作⽤ ⼀等函数的理念可以追溯到 Church 的 lambda 演算 (Church 1941; Barendregt 1984)。此后,包括 Haskell,OCaml,Standard ML,Scala 和 F# 在内的⼤量 (函数式) 编程语⾔都不同程度地借鉴了这个概念。 PS:世界上最纯粹的函数式编程语⾔⾮Haskell莫属。 函数式编程强调没有"副作⽤",意味着函数要保持 独⽴,所有功能就是返回⼀个新的值,没有其他⾏ 为,尤其是不得修改外部变量的值。

Slide 7

Slide 7 text

函数式编程Functional Programming 1. 函数是"第⼀等公⺠" 2. 闭包和⾼阶函数 3. 不改变状态 4. 递归 5. 只⽤"表达式",不⽤"语句",没有副作⽤ 85% 50% 76% 95% Functional Programming is a programming paradigm 1. treats computation as the evaluation of mathematical functions. 2. avoids changing-state and mutable data 所谓"第⼀等公⺠"(first class),指的是函数与其他数据类型⼀样,处于平等地位,可以赋值给其他变量,也可 以作为参数,传⼊另⼀个函数,或者作为别的函数的返回值。

Slide 8

Slide 8 text

函数响应式编程FUNCTIONAL REACTIVE PROGRAMMING 函数响应式编程是⾯向离散事件流的,在⼀个时间轴上会产⽣ ⼀些离散事件,这些事件会依次向下传递。 RAC就是Cocoa框架下的函数响应式编程的实现。它提供了基 于时间变化的数据流的组合和变化。 明⽩了!

Slide 9

Slide 9 text

⾯向对象编程 Object Oriented Programming 响应式编程 Reactive Programming 函数式编程 Functional Programming 函数响应式编程 Functional Reactive Programming

Slide 10

Slide 10 text

Tortor Sem Dapibus

Slide 11

Slide 11 text

Tortor Sem Dapibus

Slide 12

Slide 12 text

Github Mac 客户端附产物 01 FRP在Cocoa框架下的实现 02 富含了Cocoa框架下的多种组 件 03 提供了基于时间变化的数据流 的组合和变换的操作 04 简称 RAC 05 什么是 ReactiveCoCoa ?

Slide 13

Slide 13 text

Reactive Objc

Slide 14

Slide 14 text

RACSequence VS RACSignal Pull-Driver Data Push-Driver Event

Slide 15

Slide 15 text

RACDisposable RACScheduler RACCommand RACSubscriber

Slide 16

Slide 16 text

RAC 基础 RACSignal *signal = [RACSignal createSignal: ^RACDisposable *(id subscriber) { [subscriber sendNext:@1]; [subscriber sendNext:@2]; [subscriber sendNext:@3]; [subscriber sendCompleted]; return [RACDisposable disposableWithBlock:^{ NSLog(@"signal dispose"); }]; }]; RACDisposable *disposable = [signal subscribeNext:^(id x) { NSLog(@"subscribe value = %@", x); } error:^(NSError *error) { NSLog(@"error: %@", error); } completed:^{ NSLog(@"completed"); }]; [disposable dispose];

Slide 17

Slide 17 text

单个信号的变换 RACSignal 的各类操作

Slide 18

Slide 18 text

RACSignal

Slide 19

Slide 19 text

RACSignal

Slide 20

Slide 20 text

RACSignal

Slide 21

Slide 21 text

RACSignal

Slide 22

Slide 22 text

RACSignal

Slide 23

Slide 23 text

RACSignal

Slide 24

Slide 24 text

RACSignal

Slide 25

Slide 25 text

RACSignal

Slide 26

Slide 26 text

RACSignal

Slide 27

Slide 27 text

85% 50% 76% 95% 数量操作 RACSignal 的各类操作

Slide 28

Slide 28 text

RACSignal

Slide 29

Slide 29 text

RACSignal

Slide 30

Slide 30 text

RACSignal

Slide 31

Slide 31 text

RACSignal

Slide 32

Slide 32 text

RACSignal

Slide 33

Slide 33 text

RACSignal

Slide 34

Slide 34 text

RACSignal

Slide 35

Slide 35 text

RACSignal

Slide 36

Slide 36 text

RACSignal

Slide 37

Slide 37 text

RACSignal

Slide 38

Slide 38 text

RACSignal

Slide 39

Slide 39 text

RACSignal

Slide 40

Slide 40 text

RACSignal

Slide 41

Slide 41 text

RACSignal Repeat 操作 Signal A ——‘AA’——‘BB’—|————————— Signal B ——‘AA’——‘BB’———‘AA’——‘BB’———‘AA’——‘BB’—

Slide 42

Slide 42 text

时间操作 RACSignal 的各类操作

Slide 43

Slide 43 text

RACSignal + (RACSignal *)interval:(NSTimeInterval)interval onScheduler:(RACScheduler *)scheduler;

Slide 44

Slide 44 text

RACSignal 如何得到⼀个每隔⼀秒延迟发送⼀个值的⽆限信号? (假设每个值都是1,即[RACSignal return:@1]) RACSignal *interval = [[[RACSignal return:@1] delay:1] repeat]; 如何把下⾯这个信号每个值中间都插⼊1秒的时间间隔? RACSignal *signal = @[@1, @3, @7, @9, @8].rac_sequence.signal; RACSignal *timerSignal = [[signal map:^id(id value) { return [[RACSignal return:value] delay:1]; }] concat];

Slide 45

Slide 45 text

RACSignal

Slide 46

Slide 46 text

多个信号的组合 RACSignal 的各类操作

Slide 47

Slide 47 text

RACSignal

Slide 48

Slide 48 text

RACSignal

Slide 49

Slide 49 text

RACSignal

Slide 50

Slide 50 text

RACSignal

Slide 51

Slide 51 text

RACSignal

Slide 52

Slide 52 text

RACSignal

Slide 53

Slide 53 text

Q & A

Slide 54

Slide 54 text

ANSWER 1. RAC 在哪些场景下可以提⾼开发效率? 可否举个最明显的例⼦。 2. RAC 有哪些缺陷?⽐如RAC的哪些操作 执⾏效率⽐较低? 3. 如何降低新同事的学习成本?即有⽊有 快速⼊⻔的系列教程可以推荐,适合⼊ ⻔的,中级的,深⼊的。 4. ReactiveCocoa 和 ReactiveSwift 啥关 系? ⼊⻔资料官⽅⽂档 基础⽤法都要熟悉 先回答第三题 中级 多实践,思维的转变,⽤函数式 去思考问题 深⼊ 看源码,了解底层实现,领悟 RAC的精髓。如何不⽤RAC实现 MVVM中的绑定操作?bind 和 Monad 范畴论

Slide 55

Slide 55 text

2 3 1 RAC适合的场景 事件处理 切⾯处理 异步场景

Slide 56

Slide 56 text

处理成功的回调 01 处理异常和错误 02 ⽀持取消操作 03 subscribenext 01 subscribeError 02 disposable 03 异步处理 还能有效解决回调地狱的问题 PromiseKit (PromiseKit 是 RAC的 Continuation-Passing Style)

Slide 57

Slide 57 text

异步处理 信号的降阶 和升阶 错误传递和 捕获的统⼀ 信号的组合 与变换 线程操作RACScheduler⽅便 01 02 03

Slide 58

Slide 58 text

UI事件 事件处理 Delegate RAC对整个UIKit库都有对应的 Category

Slide 59

Slide 59 text

切⾯处理 KVO ⽅法调⽤与监听

Slide 60

Slide 60 text

同步场景 14% 68% 47% RAC不适合的场景 纯OOP场景 缺陷 调试困难 对新⼿不友好 学习曲线陡峭

Slide 61

Slide 61 text

09:30 Magna Amet 05:20 AM 09:45 PM Euismod, Ipsum ReactiveSwift 是 RAC 在 Swift 语⾔出来以后针对 Swift 的实现。 ReactiveSwift ⾥⾯没有冷信号。全是热信号。 ReactiveSwif 在ReactiveCocoa v2.5中,flatten默认就是flattenMap:这 ⼀种操作。 ReactiveCocoa v3.x,v4.x,v5.x中,flatten的操作是可以 选择3种操作选择的。merge,concat,switchToLatest。 ReactiveCocoa 和 ReactiveSwift

Slide 62

Slide 62 text

ANSWER 1. RAC 和 Rx 对⽐ 2. MVVM 实践探讨,哪⾥该⽤哪⾥不该⽤ 3. 双向绑定 vs 单向绑定 4. 如何将事件传递流暴露的更明显,⽽不是 像 notify ⼀样分散 1.RAC 和 Rx 都是采⽤ FRP 思想 实现的⼀个库。RAC有OC版 本,Rx只有Swift版本。Rx家族 API特别⼀致。 第⼆题请⽼⼤回答 3.双向绑定: 当⼀个⼦组件改变了⼀个prop的值 时,这个变化也会同步到⽗组件中所 绑定的值。但也会导致问题。由于⼦ 组件改变prop的代码和普通的状态改 变代码毫⽆差别,当光看⼦组件的代 码时,你完全不知道它何时悄悄地改 变了⽗组件的状态。这在debug复杂 结构的应⽤时会带来很⾼的维护成 本。 4.⽤⼀个消息中⼼或者消息总线来处理

Slide 63

Slide 63 text

THANK YOU.