<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>RAC on prometheus</title><link>https://new.halfrost.com/zh/tags/rac/</link><description>Recent content in RAC on prometheus</description><generator>Hugo -- gohugo.io</generator><language>zh-CN</language><copyright>halfrost</copyright><lastBuildDate>Sun, 12 Feb 2017 05:46:54 +0000</lastBuildDate><atom:link href="https://new.halfrost.com/zh/tags/rac/index.xml" rel="self" type="application/rss+xml"/><item><title>ReactiveCocoa 中 奇妙无比的“宏”魔法</title><link>https://new.halfrost.com/zh/reactivecocoa_macro/</link><pubDate>Sun, 12 Feb 2017 05:46:54 +0000</pubDate><guid>https://new.halfrost.com/zh/reactivecocoa_macro/</guid><description>前言 在ReactiveCocoa 中，开源库作者为我们提供了很多种魔法，“黑”魔法，“红”魔法……今天就让先来看看“红”魔法。
在ReactiveCocoa 中，封装了很多非常实用的“宏”，使用这些“宏”为我们开发带来了很多的便利。
今天就来盘点一下RAC中的宏是如何实现的。
目录 1.关于宏 2.ReactiveCocoa 中的元宏 3.ReactiveCocoa 中常用的宏 一. 关于宏 宏（Macro），是一种批量处理的称谓。
在编程领域里的宏是一种抽象（Abstraction），它根据一系列预定义的规则替换一定的文本模式。解释器或编译器在遇到宏时会自动进行这一模式替换。绝大多数情况下，“宏”这个词的使用暗示着将小命令或动作转化为一系列指令。
宏的用途在于自动化频繁使用的序列或者是获得一种更强大的抽象能力。 计算机语言如C语言或汇编语言有简单的宏系统，由编译器或汇编器的预处理器实现。C语言的宏预处理器的工作只是简单的文本搜索和替换，使用附加的文本处理语言如M4，C程序员可以获得更精巧的宏。
Lisp类语言如Common Lisp和Scheme有更精巧的宏系统：宏的行为如同是函数对自身程序文本的变形，并且可以应用全部语言来表达这种变形。一个C宏可以定义一段语法的替换，然而一个Lisp的宏却可以控制一节代码的计算。
对于编译语言来说，所有的宏都是在预编译的时候被展开的，所以在lex进行词法扫描生成Token，词法分析过程之前，所有的宏都已经被展开完成了。
对于Xcode，预处理或者预编译阶段是可以直接查看的。
随便写一个宏，然后打开Xcode右上方的Assistant，选择“Preprocess”就可以看到该文件预处理之后的样子了。可以看到左边的@weakify(self) 被转换成了右边的两行代码了。
关于这个Xcode的这个功能还有2点补充说明：
1.不同阶段的Preprocessed可能不同，要根据你的目标去选择预处理的条件。
比如这里就有5种预编译的种类可以选择。
2.宏经过预编译之后出来的代码，是可以用来检测宏写的是否正确的，但是无法看到宏被展开的具体过程。这意味着我们可以通过Xcode这个功能来查看宏的作用，但是无法知道宏的具体实现。具体实现还是需要通过查看源码来分析。
ReactiveCocoa中的宏，如果不查看源码分析，会觉得那些宏都像魔法一样奇妙无比，接下来就来解开“宏”魔法的神秘面纱。
二. ReactiveCocoa 中的元宏 在ReactiveCocoa的宏中，作者定义了这么一些基础的宏，作为“元宏”，它们是构成之后复杂宏的基础。在分析常用宏之前，必须要先分析清楚这些元宏的具体实现。
1. metamacro_stringify(VALUE) #define metamacro_stringify(VALUE) \ metamacro_stringify_(VALUE) #define metamacro_stringify_(VALUE) # VALUE metamacro_stringify( )这个宏用到了#的用法。#在宏中代表把宏的参数变为一个字符串。这个宏的目的和它的名字一样明显，把入参VALUE转换成一个字符串返回。
这里可能就有人有疑问，为啥要包装一层，不能直接写成下面这样：
#define metamacro_stringify(VALUE) # VALUE 语意确实也没有变，但是有种特殊情况下就会出现问题。
举个例子：
#define NUMBER 10 #define ADD(a,b) (a+b) NSLog(@&amp;#34;%d+%d=%d&amp;#34;,NUMBER, NUMBER, ADD(NUMBER,NUMBER)); 输出如下：
10+10=20这样子确实是没有问题，但是稍作修改就会有问题。</description></item><item><title>ReactiveCocoa 中 RACCommand 底层实现分析</title><link>https://new.halfrost.com/zh/reactivecocoa_raccommand/</link><pubDate>Sat, 07 Jan 2017 01:59:00 +0000</pubDate><guid>https://new.halfrost.com/zh/reactivecocoa_raccommand/</guid><description>前言 在ReactiveCocoa 过程中，除去RACSignal和RACSubject这些信号类以外，有些时候我们可能还需要封装一些固定的操作集合。这些操作集合都是固定的，每次只要一触发就会执行事先定义好的一个过程。在iOS开发过程中，按钮的点击事件就可能有这种需求。那么RACCommand就可以实现这种需求。
当然除了封装一个操作集合以外，RACCommand还能集中处理错误等等功能。今天就来从底层来看看RACCommand是如何实现的。
目录 1.RACCommand的定义 2.initWithEnabled: signalBlock: 底层实现分析 3.execute:底层实现分析 4.RACCommand的一些Category 一. RACCommand的定义 首先说说RACCommand的作用。 RACCommand 在ReactiveCocoa 中是对一个动作的触发条件以及它产生的触发事件的封装。
触发条件：初始化RACCommand的入参enabledSignal就决定了RACCommand是否能开始执行。入参enabledSignal就是触发条件。举个例子，一个按钮是否能点击，是否能触发点击事情，就由入参enabledSignal决定。
触发事件：初始化RACCommand的另外一个入参(RACSignal * (^)(id input))signalBlock就是对触发事件的封装。RACCommand每次执行都会调用一次signalBlock闭包。
RACCommand最常见的例子就是在注册登录的时候，点击获取验证码的按钮，这个按钮的点击事件和触发条件就可以用RACCommand来封装，触发条件是一个信号，它可以是验证手机号，验证邮箱，验证身份证等一些验证条件产生的enabledSignal。触发事件就是按钮点击之后执行的事件，可以是发送验证码的网络请求。
RACCommand在ReactiveCocoa中算是很特别的一种存在，因为它的实现并不是FRP实现的，是OOP实现的。RACCommand的本质就是一个对象，在这个对象里面封装了4个信号。
关于RACCommand的定义如下：
@interface RACCommand : NSObject @property (nonatomic, strong, readonly) RACSignal *executionSignals; @property (nonatomic, strong, readonly) RACSignal *executing; @property (nonatomic, strong, readonly) RACSignal *enabled; @property (nonatomic, strong, readonly) RACSignal *errors; @property (atomic, assign) BOOL allowsConcurrentExecution; volatile uint32_t _allowsConcurrentExecution; @property (atomic, copy, readonly) NSArray *activeExecutionSignals; NSMutableArray *_activeExecutionSignals; @property (nonatomic, strong, readonly) RACSignal *immediateEnabled; @property (nonatomic, copy, readonly) RACSignal * (^signalBlock)(id input); @end RACCommand中4个最重要的信号就是定义开头的那4个信号，executionSignals，executing，enabled，errors。需要注意的是，这4个信号基本都是（并不是完全是）在主线程上执行的。</description></item><item><title>ReactiveCocoa 中 RACScheduler 是如何封装 GCD 的</title><link>https://new.halfrost.com/zh/reactivecocoa_racscheduler/</link><pubDate>Sat, 31 Dec 2016 01:09:00 +0000</pubDate><guid>https://new.halfrost.com/zh/reactivecocoa_racscheduler/</guid><description>前言 在使用ReactiveCocoa 过程中，Josh Abernathy和Justin Spahr-Summers 两位大神为了能让RAC的使用者更畅快的在沉浸在FRP的世界里，更好的进行并发编程，于是就对GCD进行了一次封装，并与RAC的各大组件进行了完美的整合。
自从有了RACScheduler以后，使整个RAC并发编程的代码里面更加和谐统一，更加顺手，更加“ReactiveCocoa”。
目录 1.RACScheduler是如何封装GCD的 2.RACScheduler的一些子类 3.RACScheduler是如何“取消”并发任务的 4.RACScheduler是如何和RAC其他组件进行完美整合的 一. RACScheduler是如何封装GCD的 RACScheduler在ReactiveCocoa中到底是干嘛的呢？处于什么地位呢？官方给出的定义如下：
Schedulers are used to control when and where work is performedRACScheduler在ReactiveCocoa中是用来控制一个任务，何时何地被执行。它主要是用来解决ReactiveCocoa中并发编程的问题的。
RACScheduler的实质是对GCD的封装，底层就是GCD实现的。
要分析RACScheduler，先来回顾一下GCD。
众所周知，在GCD中，Dispatch Queue主要分为2类，Serial Dispatch Queue 和 Concurrent Dispatch Queue 。其中Serial Dispatch Queue是等待现在执行中处理结束的队列，Concurrent Dispatch Queue是不等待现在执行中处理结束的队列。
生成Dispatch Queue的方法也有2种，第一种方式是通过GCD的API生成Dispatch Queue。
生成Serial Dispatch Queue
dispatch_queue_t serialDispatchQueue = dispatch_queue_create(&amp;#34;com.gcd.SerialDispatchQueue&amp;#34;, DISPATCH_QUEUE_SERIAL); 生成Concurrent Dispatch Queue
dispatch_queue_t concurrentDispatchQueue = dispatch_queue_create(&amp;#34;com.gcd.ConcurrentDispatchQueue&amp;#34;, DISPATCH_QUEUE_CONCURRENT); 第二种方法是直接获取系统提供的Dispatch Queue。系统提供的也分为2类，Main Dispatch Queue 和 Global Dispatch Queue。Main Dispatch Queue 对应着是Serial Dispatch Queue，Global Dispatch Queue 对应着是Concurrent Dispatch Queue。</description></item><item><title>ReactiveCocoa 中 集合类 RACSequence 和 RACTuple 底层实现分析</title><link>https://new.halfrost.com/zh/reactivecocoa_racsequence_ractuple/</link><pubDate>Sun, 25 Dec 2016 07:54:00 +0000</pubDate><guid>https://new.halfrost.com/zh/reactivecocoa_racsequence_ractuple/</guid><description>前言 在OOP的世界里使用FRP的思想来编程，光有函数这种一等公民，还是无法满足我们一些需求的。因此还是需要引用变量来完成各式各样的类的操作行为。
在前几篇文章中详细的分析了RACStream中RACSignal的底层实现。RACStream还有另外一个子类，RACSequence，这个类是RAC专门为集合而设计的。这篇文章就专门分析一下RACSequence的底层实现。
目录 1.RACTuple底层实现分析 2.RACSequence底层实现分析 3.RACSequence操作实现分析 4.RACSequence的一些扩展 一. RACTuple底层实现分析 在分析RACSequence之前，先来看看RACTuple的实现。RACTuple是ReactiveCocoa的元组类。
1. RACTuple @interface RACTuple : NSObject &amp;lt;NSCoding, NSCopying, NSFastEnumeration&amp;gt; @property (nonatomic, readonly) NSUInteger count; @property (nonatomic, readonly) id first; @property (nonatomic, readonly) id second; @property (nonatomic, readonly) id third; @property (nonatomic, readonly) id fourth; @property (nonatomic, readonly) id fifth; @property (nonatomic, readonly) id last; @property (nonatomic, strong) NSArray *backingArray; @property (nonatomic, copy, readonly) RACSequence *rac_sequence; // 这个是专门为sequence提供的一个扩展 @end RACTuple的定义看上去很简单，底层实质就是一个NSArray，只不过封装了一些方法。RACTuple继承了NSCoding, NSCopying, NSFastEnumeration这三个协议。</description></item><item><title>ReactiveCocoa 中 RACSignal 所有变换操作底层实现分析(下)</title><link>https://new.halfrost.com/zh/reactivecocoa_racsignal_operations3/</link><pubDate>Sat, 10 Dec 2016 09:12:00 +0000</pubDate><guid>https://new.halfrost.com/zh/reactivecocoa_racsignal_operations3/</guid><description>前言 紧接着上篇的源码实现分析，继续分析RACSignal的变换操作的底层实现。
目录 1.高阶信号操作 2.同步操作 3.副作用操作 4.多线程操作 5.其他操作 一. 高阶信号操作 高阶操作大部分的操作是针对高阶信号的，也就是说信号里面发送的值还是一个信号或者是一个高阶信号。可以类比数组，这里就是多维数组，数组里面还是套的数组。
1. flattenMap: (在父类RACStream中定义的) flattenMap:在整个RAC中具有很重要的地位，很多信号变换都是可以用flattenMap:来实现的。
map:，flatten，filter，sequenceMany:这4个操作都是用flattenMap:来实现的。然而其他变换操作实现里面用到map:，flatten，filter又有很多。
回顾一下map:的实现：
- (instancetype)map:(id (^)(id value))block { NSCParameterAssert(block != nil); Class class = self.class; return [[self flattenMap:^(id value) { return [class return:block(value)]; }] setNameWithFormat:@&amp;#34;[%@] -map:&amp;#34;, self.name]; } map:的操作其实就是直接原信号进行的 flattenMap:的操作，变换出来的新的信号的值是block(value)。
flatten的实现接下去会具体分析，这里先略过。
filter的实现：
- (instancetype)filter:(BOOL (^)(id value))block { NSCParameterAssert(block != nil); Class class = self.class; return [[self flattenMap:^ id (id value) { block(value) ? return [class return:value] : return class.</description></item><item><title>ReactiveCocoa 中 RACSignal 冷信号和热信号底层实现分析</title><link>https://new.halfrost.com/zh/reactivecocoa_hot_cold_signal/</link><pubDate>Sun, 04 Dec 2016 22:15:00 +0000</pubDate><guid>https://new.halfrost.com/zh/reactivecocoa_hot_cold_signal/</guid><description>前言 关于ReactiveCocoa v2.5中冷信号和热信号的文章中，最著名的就是美团的臧成威老师写的3篇冷热信号的文章：
细说ReactiveCocoa的冷信号与热信号（一）
细说ReactiveCocoa的冷信号与热信号（二）：为什么要区分冷热信号
细说ReactiveCocoa的冷信号与热信号（三）：怎么处理冷信号与热信号
由于最近在写关于RACSignal底层实现分析的文章，当然也逃不了关于冷热信号操作的分析。这篇文章打算分析分析如何从冷信号转成热信号的底层实现。
目录 1.关于冷信号和热信号的概念 2.RACSignal热信号 3.RACSignal冷信号 4.冷信号是如何转换成热信号的 一. 关于冷信号和热信号的概念 冷热信号的概念是源自于源于.NET框架Reactive Extensions(RX)中的Hot Observable和Cold Observable，
Hot Observable是主动的，尽管你并没有订阅事件，但是它会时刻推送，就像鼠标移动；而Cold Observable是被动的，只有当你订阅的时候，它才会发布消息。
Hot Observable可以有多个订阅者，是一对多，集合可以与订阅者共享信息；而Cold Observable只能一对一，当有不同的订阅者，消息是重新完整发送。
在这篇文章细说ReactiveCocoa的冷信号与热信号（一）详细分析了冷热信号的特点：
热信号是主动的，即使你没有订阅事件，它仍然会时刻推送。而冷信号是被动的，只有当你订阅的时候，它才会发送消息。
热信号可以有多个订阅者，是一对多，信号可以与订阅者共享信息。而冷信号只能一对一，当有不同的订阅者，消息会从新完整发送。
二. RACSignal热信号 RACSignal家族中符合热信号的特点的信号有以下几个。
1.RACSubject @interface RACSubject : RACSignal &amp;lt;RACSubscriber&amp;gt; @property (nonatomic, strong, readonly) NSMutableArray *subscribers; @property (nonatomic, strong, readonly) RACCompoundDisposable *disposable; - (void)enumerateSubscribersUsingBlock:(void (^)(id&amp;lt;RACSubscriber&amp;gt; subscriber))block; + (instancetype)subject; @end 首先来看看RACSubject的定义。
RACSubject是继承自RACSignal，并且它还遵守RACSubscriber协议。这就意味着它既能订阅信号，也能发送信号。
在RACSubject里面有一个NSMutableArray数组，里面装着该信号的所有订阅者。其次还有一个RACCompoundDisposable信号，里面装着该信号所有订阅者的RACDisposable。
RACSubject之所以能称之为热信号，那么它肯定是符合上述热信号的定义的。让我们从它的实现来看看它是如何符合的。
- (RACDisposable *)subscribe:(id&amp;lt;RACSubscriber&amp;gt;)subscriber { NSCParameterAssert(subscriber !</description></item><item><title>ReactiveCocoa 中 RACSignal 所有变换操作底层实现分析(中)</title><link>https://new.halfrost.com/zh/reactivecocoa_racsignal_operations2/</link><pubDate>Tue, 29 Nov 2016 20:52:00 +0000</pubDate><guid>https://new.halfrost.com/zh/reactivecocoa_racsignal_operations2/</guid><description>前言 紧接着上篇的源码实现分析，继续分析RACSignal的变换操作的底层实现。
目录 1.过滤操作 2.组合操作 一. 过滤操作 过滤操作也属于一种变换，根据过滤条件，过滤出符合条件的值。变换出来的新的信号是原信号的一个子集。
1. filter: (在父类RACStream中定义的) 这个filter:操作在any:的实现中用到过了。
- (instancetype)filter:(BOOL (^)(id value))block { NSCParameterAssert(block != nil); Class class = self.class; return [[self flattenMap:^ id (id value) { if (block(value)) { return [class return:value]; } else { return class.empty; } }] setNameWithFormat:@&amp;#34;[%@] -filter:&amp;#34;, self.name]; } filter:中传入一个闭包，是用筛选的条件。如果满足筛选条件的即返回原信号的值，否则原信号的值被“吞”掉，返回空的信号。这个变换主要是用flattenMap的。
2. ignoreValues - (RACSignal *)ignoreValues { return [[self filter:^(id _) { return NO; }] setNameWithFormat:@&amp;#34;[%@] -ignoreValues&amp;#34;, self.name]; } 由上面filter的实现，这里把筛选判断条件永远的传入NO，那么原信号的值都会被变换成empty信号，故变换之后的信号为空信号。</description></item><item><title>ReactiveCocoa 中 RACSignal 所有变换操作底层实现分析(上)</title><link>https://new.halfrost.com/zh/reactivecocoa_racsignal_operations1/</link><pubDate>Sat, 26 Nov 2016 00:42:12 +0000</pubDate><guid>https://new.halfrost.com/zh/reactivecocoa_racsignal_operations1/</guid><description>前言 在上篇文章中，详细分析了RACSignal是创建和订阅的详细过程。看到底层源码实现后，就能发现，ReactiveCocoa这个FRP的库，实现响应式（RP）是用Block闭包来实现的，而并不是用KVC / KVO实现的。
在ReactiveCocoa整个库中，RACSignal占据着比较重要的位置，而RACSignal的变换操作更是整个RACStream流操作核心之一。在上篇文章中也详细分析了bind操作的实现。RACsignal很多变换操作都是基于bind操作来实现的。在开始本篇底层实现分析之前，先简单回顾一下上篇文章中分析的bind函数，这是这篇文章分析的基础。
bind函数可以简单的缩写成下面这样子。
- (RACSignal *)bind:(RACStreamBindBlock (^)(void))block; { return [RACSignal createSignal:^RACDisposable *(id&amp;lt;RACSubscriber&amp;gt; subscriber) { RACStreamBindBlock bindBlock = block(); [self subscribeNext:^(id x) { //(1)  BOOL stop = NO; RACSignal *signal = (RACSignal *)bindBlock(x, &amp;amp;stop); //(2)  if (signal == nil || stop) { [subscriber sendCompleted]; } else { [signal subscribeNext:^(id x) { [subscriber sendNext:x]; //(3)  } error:^(NSError *error) { [subscriber sendError:error]; } completed:^{ }]; } } error:^(NSError *error) { [subscriber sendError:error]; } completed:^{ [subscriber sendCompleted]; }]; return nil; }]; } 当bind变换之后的信号被订阅，就开始执行bind函数中return的block闭包。</description></item><item><title>ReactiveCocoa 中 RACSignal 是如何发送信号的</title><link>https://new.halfrost.com/zh/reactivecocoa_racsignal/</link><pubDate>Mon, 14 Nov 2016 09:48:43 +0000</pubDate><guid>https://new.halfrost.com/zh/reactivecocoa_racsignal/</guid><description>前言 ReactiveCocoa是一个(第一个？)将函数响应式编程范例带入Objective-C的开源库。ReactiveCocoa是由Josh Abernathy和Justin Spahr-Summers 两位大神在对GitHub for Mac的开发过程中编写的。Justin Spahr-Summers 大神在2011年11月13号下午12点35分进行的第一次提交，直到2013年2月13日上午3点05分发布了其1.0 release，达到了第一个重要里程碑。ReactiveCocoa社区也非常活跃，目前最新版已经完成了ReactiveCocoa 5.0.0-alpha.3，目前在5.0.0-alpha.4开发中。
ReactiveCocoa v2.5 是公认的Objective-C最稳定的版本，因此被广大的以OC为主要语言的客户端选中使用。ReactiveCocoa v3.x主要是基于Swift 1.2的版本，而ReactiveCocoa v4.x 主要基于Swift 2.x，ReactiveCocoa 5.0就全面支持Swift 3.0，也许还有以后的Swift 4.0。接下来几篇博客先以ReactiveCocoa v2.5版本为例子，分析一下OC版的RAC具体实现（也许分析完了RAC 5.0就到来了）。也算是写在ReactiveCocoa 5.0正式版到来前夕的祝福吧。
目录 1.什么是ReactiveCocoa？ 2.RAC中的核心RACSignal发送与订阅流程 3.RACSignal操作的核心bind实现 4.RACSignal基本操作concat和zipWith实现 5.最后 一. 什么是ReactiveCocoa？ ReactiveCocoa（其简称为RAC）是由Github 开源的一个应用于iOS和OS X开发的新框架。RAC具有函数式编程(FP)和响应式编程(RP)的特性。它主要吸取了.Net的 Reactive Extensions的设计和实现。
ReactiveCocoa 的宗旨是Streams of values over time ，随着时间变化而不断流动的数据流。
ReactiveCocoa 主要解决了以下这些问题：
UI数据绑定 UI控件通常需要绑定一个事件，RAC可以很方便的绑定任何数据流到控件上。
用户交互事件绑定 RAC为可交互的UI控件提供了一系列能发送Signal信号的方法。这些数据流会在用户交互中相互传递。
解决状态以及状态之间依赖过多的问题 有了RAC的绑定之后，可以不用在关心各种复杂的状态，isSelect，isFinish……也解决了这些状态在后期很难维护的问题。
消息传递机制的大统一 OC中编程原来消息传递机制有以下几种：Delegate，Block Callback，Target-Action，Timers，KVO，objc上有一篇关于OC中这5种消息传递方式改如何选择的文章Communication Patterns，推荐大家阅读。现在有了RAC之后，以上这5种方式都可以统一用RAC来处理。
二. RAC中的核心RACSignal ReactiveCocoa 中最核心的概念之一就是信号RACStream。RACStream中有两个子类——RACSignal 和 RACSequence。本文先来分析RACSignal。</description></item><item><title>函数响应式编程(FRP)从入门到"放弃"——图解RACSignal篇</title><link>https://new.halfrost.com/zh/ios_rac_racsignal/</link><pubDate>Sun, 24 Jul 2016 10:54:00 +0000</pubDate><guid>https://new.halfrost.com/zh/ios_rac_racsignal/</guid><description>目录 1.RACSignal的创建 2.RACSignal的订阅 3.RACSignal各类操作 ####一.RACSignal的创建
1.创建单元信号
NSError *errorObject = [NSError errorWithDomain:@&amp;quot;Something wrong&amp;quot; code:500 userInfo:nil]; //基本的4种创建方法 RACSignal *signal1 = [RACSignal return:@&amp;quot;Some Value&amp;quot;]; RACSignal *signal2 = [RACSignal error:errorObject]; RACSignal *signal3 = [RACSignal empty]; RACSignal *signal4 = [RACSignal never]; 2.创建动态信号
RACSignal *signal5 = [RACSignal createSignal: ^RACDisposable *(id&amp;lt;RACSubscriber&amp;gt; subscriber) { [subscriber sendNext:@1]; [subscriber sendNext:@2]; [subscriber sendError:errorObject]; [subscriber sendCompleted]; return [RACDisposable disposableWithBlock:^{ }]; }]; 3.通过Cocoa桥接方式获得一个信号
RACSignal *signal6 = [view rac_signalForSelector:@selector(setFrame:)]; RACSignal *signal7 = [view rac_signalForControlEvents:UIControlEventTouchUpInside]; RACSignal *signal8 = [view rac_willDeallocSignal]; //KVO的原理实现 RACSignal *signal9 = RACObserve(view, backgroundColor); 4.</description></item><item><title>函数响应式编程 ( FRP ) 从入门到"放弃"——基础概念篇</title><link>https://new.halfrost.com/zh/functional_reactive_programming_concept/</link><pubDate>Mon, 11 Jul 2016 01:24:00 +0000</pubDate><guid>https://new.halfrost.com/zh/functional_reactive_programming_concept/</guid><description>前言 研究ReactiveCocoa一段时间了，是时候总结一下学到的一些知识了。
一.函数响应式编程 说道函数响应式编程，就不得不提到函数式编程，它们俩到底有什么关系呢？今天我们就详细的解析一下他们的关系。
现在有下面4个概念，需要我们理清一下它们之间的关系：
面向对象编程 Object Oriented Programming
响应式编程 Reactive Programming
函数式编程 Functional Programming
函数响应式编程 Functional Reactive Programming
我们先来说说什么是函数式编程Functional Programming，我们先来看看wikipedia上的相关定义：
Functional Programming is a programming paradigm
treats computation as the evaluation of mathematical functions. avoids changing-state and mutable data 总结一下函数式编程具有以下几个特点：
函数是&amp;quot;第一等公民&amp;rdquo; 闭包和高阶函数 不改变状态(由此延伸出”引用透明”的概念) 递归 只用&amp;quot;表达式&amp;rdquo;，不用&amp;quot;语句&amp;rdquo;，没有副作用 接下来我们依次说明一下这些特点。
一. 函数是&amp;quot;第一等公民&amp;rdquo; 所谓&amp;quot;第一等公民&amp;rdquo;（first class），指的是函数与其他数据类型一样，处于平等地位，可以赋值给其他变量，也可以作为参数，传入另一个函数，或者作为别的函数的返回值。
一等函数的理念可以追溯到 Church 的 lambda 演算 (Church 1941; Barendregt 1984)。此后，包括 Haskell，OCaml，Standard ML，Scala 和 F# 在内的大量 (函数式) 编程语言都不同程度地借鉴了这个概念。</description></item></channel></rss>