对《The future of ReactiveCocoa》的一些思考
前言
我以为
第一次接触 swift 语言时,看到函数的表示形式如下:
func fun(num: Int) -> Int {
return num + 1
}
let f = fun(1)
和Objective-C对比一下:
- (int)fun:(int)num
{
return num + 1;
}
int f = [self fun:1];
我们很容易就认为 ->
和Objective-C里面的 -
一样嘛,一种修饰符而已,-> Int
和 - (int)
就是一个东西嘛!只不过 swift 在后面(和Golang的函数定义蛮像的,Golang没有这个->
而已。),OC在前而已,新语言嘛,要和古老的 OC 有所区别的嘛。
() -> ()
回想一下C语言的函数指针
定义,可以定义一个函数指针为:
typedef int (*funPointer)(int); // funPointer = int (*)(int)
如果按此举一反三的话,那么 swift 版的 fun
就可以看成这样:
fun = (Int) -> Int
把参数什么的都去掉,变成如下:
fun = () -> ()
() -> ()
就是我们今天讨论的重点了。()
表示数据,->
表示运算过程,fun
函数就是从输入一个数据,到得到一个数据的过程, 即值的变化过程。
()
() -> ()
表示值的变化的过程,是函数式编程范式
的一种高度抽象,表示了一个函数式编程思想。
swift 本身就支持函数式编程,而在 swift 语言中,()
可以表示为一个空的 元组
,而元组
可以表示任何的值。
- 0-Tuple表示空值,也是Void的别名。
- 1-Tuple表示任意类型的实例,如(Int,String,Enum,Struct等等),也就是
Int
可以看作是一个(Int)
,String 是一个(String)
,以此类推。- N-Tuple表示多个值的组合,如
(2, "A")
、(2, "B", Struct)
等。
Tuple的详细知识请参考 Tuples(Medium Link)
在编程中,数据
和 运算
这两核心就可以在 swift 中抽象成 () -> ()
了,一切的数据都可以被抽象成 ()
, 一切的运算过程都被抽象成 ->
,那么之前认为->
只不过是新语言标新立异于古老的 OC 而放在后面的想法就是不成立的了,->
表示数据流动的方向,从一个数据到另一个数据。
到RAC中去
熟知RAC的同学都知道,RAC中有三种Event
,分别为next
,error
,completed
。而RAC中的Signal
(以RACSignal
为代表)会发送事件流(a stream of events)
给订阅者(Subscribers)
。不熟悉的请先了解RAC基本用法。
同样以RAC基本用法这篇文章里的数据流动示例图作为参考,
整个Signal
的传递过程可以抽象成(() -> ()) -> (() -> ()) -> ... -> (() -> ())
。
而RAC的作者Justin Spahr-Summers 在 GitHub Reactive Cocoa Developer Conference 上的《The Future Of ReactiveCocoa》(YTB视频)参考.NET的四种Interface
- IEnumerable
- IEnumerator
- IObservable
- IObserver
将函数式编程中的Event分为了:
- Observer(Push): Event -> ()
- Observable(Push): (E 大专栏 对《The future of ReactiveCocoa》的一些思考vent -> ()) -> ()
- Enumerator(Pull): () -> Event
- Enumerable(Pull): () -> (() -> Event)
这四种抽象的范式的表示方式和上文中通过 swift 抽象的 () -> ()
有异曲同工之妙。
将上文中的进行一下操作:
1>
(() -> ()) -> (() -> ()) -> ... -> (() -> ())
2> ‘1>’ 表达式中()
使用Event
替换
3>(Event1 -> ()) -> (Event2 -> ()) -> ... -> (EventN -> ())
,
4> ‘3>’表达式等同于Observable
的抽象。
Observer: Event -> ()
Observer
等同于RAC中的 subscriber
,当接收到一个Event
时,就执行某些操作。类似于 swift 中的 Sink
协议。
Observable: (Event -> ()) -> ()
在函数式编程中,函数作为一等公民,可以作为值传递,所以Observable
(RAC中的 Signal
) 可以接受 Observer
,当 Observer
在值传递过程中,也会执行某些操作。
Enumerator: () -> Event
到目前为止,这些都很好理解,然而硬币也有两面性,正如黑格尔的奥伏赫变一般,Observer
翻转 ->
的方向,得到 () -> Event
,
即Enumerator
,当其发生交互时,返回一个 Event
。很类似于 swift 中的 Generator
协议。
Enumerable: () -> (() -> Event)
同样翻转Observable
的->
得到 () -> (() -> Event)
,即Enumerable
。一个Enumerable
(类似于collection
)可以创建一组Enumerator
,十分接近于 swift 中的 Sequence
协议。
Push & Pull
Observer
和Observable
属于 Push 类型的,是生产者驱动的。Enumerator
和Enumerable
属于 Pull 类型的,是消费者驱动的。
Enumerator 升级
() -> Event
因为调用者必须得到一个Event
,所以只能通过同步的方式去检索值,就造成阻塞当前线程,这是不好的方式。
() -> Promise Event
() -> Promise Event
实现值通过异步的方式获取,封装每个结果到Promise
中,然后在未来的某个时间点给我们提供Event
。
同理,() -> (() -> Event)
变为 () -> (() -> Promise Event)
。
(Promises & Futures)
Promise:
- Promise 确保任务能执行
- 提供了无序和异步的功能
- 由调用者完全控制
Promise
代表了一种 延时计算
的思想,与 swift 和 Golang 中的 defer
提供的功能一样。举个例子,消费者可以立刻获取5个 Promises,但是这样就做了无用功,因为只需要从第5个开始,跳过前4个,这样前4个promise就根本不会触发,消费者完全控制。
总结
Observables 和 Enumerables 是:
- 一元运算(Monadic)
- 模块化(Modular)
- 异步的(Asynchronous)
Observables
对任意一个 observers
都是相同的。
Enumerables
对每一次枚举完全独立的。
Observables
永远都是活跃的(live)。
Enumerables
每一次的枚举都会开启新的工作(work)。
忘记Hot Signal 和 Cold Signal 吧!
Hot Signal Observables
Cold Signal Enumerables
本文根据 RAC 的作者在 2014 年的 GitHub Reactive Cocoa Developer Conference 上的《The Future Of ReactiveCocoa》(YTB视频)Talk 及 sunnyxx的博客文章:《() -> ()》 ,从 swift 的语法开始,对 RAC 的一些抽象进行了整理,试图去理解函数式编程的思想,如有出入,望不吝斧正(:/手动感谢)。
参考
对《The future of ReactiveCocoa》的一些思考的更多相关文章
- The Future Of ReactiveCocoa by Justin Spahr-Summers
https://www.bilibili.com/video/av9783052?from=search&seid=14165903430339282774
- iOS开发 ReactiveCocoa入门教程 第二部分
ReactiveCocoa 是一个框架,它允许你在你的iOS程序中使用函数响应式(FRP)技术.加上第一部分的讲解,你将会学会如何使用信号量(对事件发出数据流)如何替代标准的动作和事件处理逻辑.你也会 ...
- ReactiveCocoa入门教程:第二部分
翻译自:http://www.raywenderlich.com/62796/reactivecocoa-tutorial-pt2 原文链接: ReactiveCocoa 是一个框架,它允许你在你的i ...
- ReactiveCocoa入门教程--第二部分
翻译自:http://www.raywenderlich.com/62796/reactivecocoa-tutorial-pt2 ReactiveCocoa 是一个框架,它允许你在你的iOS程序中使 ...
- ReactiveCocoa 迎接下一个更加美好的世界
什么是ReactiveCocoa 如果你有看Github的Trending Objective-C榜单,那你肯定是见过ReactiveCocoa了.如果你在weibo上关注唐巧.onevcat等国内一 ...
- 面向未来的友好设计:Future Friendly
一年前翻译了本文的一部分,最近终于翻译完成.虽然此设计思想的提出已经好几年了,但是还是觉得应该在国内推广一下,让大家知道“内容策略”,“移动优先”,“响应式设计”,“原子设计”等设计思想和技术的根源. ...
- ReactiveCocoa代码实践之-更多思考
三.ReactiveCocoa代码实践之-更多思考 1. RACObserve()宏形参写法的区别 之前写代码考虑过 RACObserve(self.timeLabel , text) 和 RACOb ...
- 博弈论揭示了深度学习的未来(译自:Game Theory Reveals the Future of Deep Learning)
Game Theory Reveals the Future of Deep Learning Carlos E. Perez Deep Learning Patterns, Methodology ...
- 【iOS】小项目框架设计(ReactiveCocoa+MVVM+AFNetworking+FMDB)
上一个项目使用到了ReactiveCocoa+MVVM+AFNetworking+FMDB框架设计,从最初的尝试,到后来不断思考和学习,现在对这样一个整体设计还是有了一定了理解与心得.在此与大家分享下 ...
随机推荐
- 使用packstack安装pike版本的openstack
最近由于工作需要,需要调研安装pike版本的gnocchi.由于ceilometer与gnocchi版本的强相关性,所以需要部署一个同一版本的openstack环境,在同事的推荐下使用了packsta ...
- 洛谷 P1833 樱花
题目传送门 解题思路: 就是完全背包和多重背包的混合.处理时间的时候注意一下就行了 AC代码: #include<iostream> #include<cstdio> usin ...
- 21 ~ express ~ 前台内容分类展示
一,前台 , views/main/index.html ,通过get传送给后台 思路 : 将栏目ID 传递给后台,后台根据 栏目的ID 返回相应的数据 {% if category == '' ...
- HZNU-ACM寒假集训Day1小结 STL 并查集
常用STL 1.优先队列 priority_queue 内部是用堆(heap)实现的 priority_queue<int> pq; 默认为一个“越小的整数优先级越低的优先队列” 对于一些 ...
- 实验吧Web-难-头有点大(http头伪造:浏览器、国家、.Net framework版本)
进去网站显示: 此处告诉我们要干三件事: (1).net framework 版本为9.9 (2)告诉服务器我们的地址为英国 (3)我们访问站点用的是IE 下面我们就抓的包中伪造. 1:.net fr ...
- C/C++学习笔记_gdb调试
1.前提条件:可执行文件包含调试信息 gcc -g 2.gdb 文件名 ---启动gdb调试 3.查看代码的命令 当前文件: list 行号(函数名) 指定文件: list 文件名:行号(函数名)4. ...
- [WesternCTF2018]shrine
0x00 知识点 SSTI模板注入: 模板注入涉及的是服务端Web应用使用模板引擎渲染用户请求的过程 服务端把用户输入的内容渲染成模板就可能造成SSTI(Server-Side Template In ...
- 题解 Luogu P2499: [SDOI2012]象棋
关于这道题, 我们可以发现移动顺序不会改变答案, 具体来说, 我们有以下引理成立: 对于一个移动过程中的任意一个移动, 若其到达的位置上有一个棋子, 则该方案要么不能将所有棋子移动到最终位置, 要么可 ...
- JAVA多线程的基础
线程与进程的区别 1.线程与进程 每个正在系统上运行的程序都是一个进程.每个进程包含一到多个线程.线程是一组指令的集合,或者是程序的特殊段,它可以在程序里独立执行.也可以把它理解为代码运行的上下文.所 ...
- 阿里云服务器centos下安装配置svn服务器
阿里云服务器centos下安装配置svn服务器 1.安装svn服务器端yum install subversion 从镜像下载安装svn服务器端中间会提示是否ok,输入y,确认安装成功提 ...