Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Functional Reactive Programming

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

Functional Reactive Programming

Avatar for halfrost

halfrost

June 15, 2017
Tweet

More Decks by halfrost

Other Decks in Programming

Transcript

  1. 命令式 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); }
  2. 命令式 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的实现就是如此。
  3. Cum sociis natoque penatibus et magnis parturient montes. 在计算机编程中,假如满⾜下⾯这两 个句⼦的约束,⼀个函数可能被描述

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

    Haskell,OCaml,Standard ML,Scala 和 F# 在内的⼤量 (函数式) 编程语⾔都不同程度地借鉴了这个概念。 PS:世界上最纯粹的函数式编程语⾔⾮Haskell莫属。 函数式编程强调没有"副作⽤",意味着函数要保持 独⽴,所有功能就是返回⼀个新的值,没有其他⾏ 为,尤其是不得修改外部变量的值。
  5. 函数式编程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),指的是函数与其他数据类型⼀样,处于平等地位,可以赋值给其他变量,也可 以作为参数,传⼊另⼀个函数,或者作为别的函数的返回值。
  6. RAC 基础 RACSignal *signal = [RACSignal createSignal: ^RACDisposable *(id<RACSubscriber> 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];
  7. 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];
  8. ANSWER 1. RAC 在哪些场景下可以提⾼开发效率? 可否举个最明显的例⼦。 2. RAC 有哪些缺陷?⽐如RAC的哪些操作 执⾏效率⽐较低? 3.

    如何降低新同事的学习成本?即有⽊有 快速⼊⻔的系列教程可以推荐,适合⼊ ⻔的,中级的,深⼊的。 4. ReactiveCocoa 和 ReactiveSwift 啥关 系? ⼊⻔资料官⽅⽂档 基础⽤法都要熟悉 先回答第三题 中级 多实践,思维的转变,⽤函数式 去思考问题 深⼊ 看源码,了解底层实现,领悟 RAC的精髓。如何不⽤RAC实现 MVVM中的绑定操作?bind 和 Monad 范畴论
  9. 处理成功的回调 01 处理异常和错误 02 ⽀持取消操作 03 subscribenext 01 subscribeError 02

    disposable 03 异步处理 还能有效解决回调地狱的问题 PromiseKit (PromiseKit 是 RAC的 Continuation-Passing Style)
  10. 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
  11. 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.⽤⼀个消息中⼼或者消息总线来处理