前言

我以为

第一次接触 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函数就是从输入一个数据,到得到一个数据的过程, 即值的变化过程。

(sunnyxx的推导过程:《() -> ()》)

()

() -> () 表示值的变化的过程,是函数式编程范式的一种高度抽象,表示了一个函数式编程思想。
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,分别为nexterrorcompleted。而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分为了:

这四种抽象的范式的表示方式和上文中通过 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

  • ObserverObservable属于 Push 类型的,是生产者驱动的。
  • EnumeratorEnumerable 属于 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》的一些思考的更多相关文章

  1. The Future Of ReactiveCocoa by Justin Spahr-Summers

    https://www.bilibili.com/video/av9783052?from=search&seid=14165903430339282774

  2. iOS开发 ReactiveCocoa入门教程 第二部分

    ReactiveCocoa 是一个框架,它允许你在你的iOS程序中使用函数响应式(FRP)技术.加上第一部分的讲解,你将会学会如何使用信号量(对事件发出数据流)如何替代标准的动作和事件处理逻辑.你也会 ...

  3. ReactiveCocoa入门教程:第二部分

    翻译自:http://www.raywenderlich.com/62796/reactivecocoa-tutorial-pt2 原文链接: ReactiveCocoa 是一个框架,它允许你在你的i ...

  4. ReactiveCocoa入门教程--第二部分

    翻译自:http://www.raywenderlich.com/62796/reactivecocoa-tutorial-pt2 ReactiveCocoa 是一个框架,它允许你在你的iOS程序中使 ...

  5. ReactiveCocoa 迎接下一个更加美好的世界

    什么是ReactiveCocoa 如果你有看Github的Trending Objective-C榜单,那你肯定是见过ReactiveCocoa了.如果你在weibo上关注唐巧.onevcat等国内一 ...

  6. 面向未来的友好设计:Future Friendly

    一年前翻译了本文的一部分,最近终于翻译完成.虽然此设计思想的提出已经好几年了,但是还是觉得应该在国内推广一下,让大家知道“内容策略”,“移动优先”,“响应式设计”,“原子设计”等设计思想和技术的根源. ...

  7. ReactiveCocoa代码实践之-更多思考

    三.ReactiveCocoa代码实践之-更多思考 1. RACObserve()宏形参写法的区别 之前写代码考虑过 RACObserve(self.timeLabel , text) 和 RACOb ...

  8. 博弈论揭示了深度学习的未来(译自:Game Theory Reveals the Future of Deep Learning)

    Game Theory Reveals the Future of Deep Learning Carlos E. Perez Deep Learning Patterns, Methodology ...

  9. 【iOS】小项目框架设计(ReactiveCocoa+MVVM+AFNetworking+FMDB)

    上一个项目使用到了ReactiveCocoa+MVVM+AFNetworking+FMDB框架设计,从最初的尝试,到后来不断思考和学习,现在对这样一个整体设计还是有了一定了理解与心得.在此与大家分享下 ...

随机推荐

  1. 业务全都在yun上能放心吗?

    导读 组织将其业务在云上进行“全押”,这与扑克游戏中的这个激动人心时刻有着同样的吸引力.这种举动感觉很大胆,但却向外界传达了自己的信心,表明将会果断行动赢得比赛. 大多数银行对处理零售银行业务方式需要 ...

  2. POJ 1423:Big Number 求N的阶乘的长度 斯特林公式

    Big Number Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 27027   Accepted: 8626 Descr ...

  3. iOS消息转发

    消息转发是一种功能强大的技术,可以大大增加Objective-C的表现力.什么是消息转发?简而言之,它允许未知的消息被困住并作出反应.换句话说,无论何时发送未知消息,它​​都会以一个很好的包发送到您的 ...

  4. C语言预处理理论-宏定义2

    宏定义21.带参宏和带参函数的区别(1)宏定义是在预处理期间处理的,而函数是在编译期间处理的.这个区别带来的实质差异是:宏定义最终是在调用宏的地方把宏体原地展开,而函数是在调用函数处跳转到函数中去执行 ...

  5. 17 —— 服务端渲染 —— art-template

    一,前端渲染数据 的弊端 仿 apache 服务器与客户端的几次交互: 1,加载静态页面 2,加载静态资源 3,发送 ajax 请求 ,接收请求并处理返回 . 4,前端浏览器接收数据循环遍历. 存在的 ...

  6. 下页小希学MVC5+EF6.2 学习记录三

      目的:1 学习mvc+ef 2  写下日记也是对自己的督促 期待已久的EF终于来了. 学完本篇文章,你将会掌握基于EF数据模型的完整开发流程. 本次将会完成EF数据模型的搭建和使用. 基于这个模型 ...

  7. swiper实现匀速无缝滚动

    设置属性 speed:2500,//匀速时间 autoplay: { delay: 0, stopOnLastSlide: false, disableOnInteraction: true, }, ...

  8. css 居中布局方案

    position(transform css3  有些浏览器不兼容) <article id="one"> <section id="section&q ...

  9. Java 类提供了自定义的构造方法,那么类的默认构造不会被调用

    以下代码无法通过编译: public class Test1 { public static void main(String[] args) { //int a=6; Foo obj=new Foo ...

  10. contos7 共享文件夹开机自动挂载

    网上很多文章都说改文件/etc/fstab 我试了很多次都不行 然后看到另一个方法 在/etc/rc.d/rc.local 增加挂在脚本这个时候要注意执行权限问题 我是这样做的 sudo mount ...