组合
组合变换是一组多元变换形式,每次变换是由多个节点出发,经过相互计算最终向其下游节点进行传播。在实现的过程中,通常需要借助一个对象把多个变换管理起来,例如源码中的 EasyReact/Core/NodeTransforms/EZRCombineTransformGroup.h。下面介绍下全部的组合变换形式。
combine
响应式编程经常会使用 a := b + c 来举例,意图是当 b 或者 c 的值发生变化的时候,a 会保持两者的加和。那么在响应式库 EasyReact 中,我们是怎样体现的呢?就是通过 EZRCombine-mapEach 操作:
EZRMutableNode<NSNumber *> *nodeA = [EZRMutableNode value:@1];
EZRMutableNode<NSNumber *> *nodeB = [EZRMutableNode value:@2];
EZRNode<NSNumber *> *nodeC = [EZRCombine(nodeA, nodeB) mapEach:^NSNumber *(NSNumber *a, NSNumber *b) {
return @(a.integerValue + b.integerValue);
}];
nodeC.value; // <- 1 + 2 = 3
nodeA.value = @4;
nodeC.value; // <- 4 + 2 = 6
nodeB.value = @6;
nodeC.value; // <- 4 + 6 = 10
merge
合并操作其实很好理解,合并多个节点作为上游,当任何一个节点有新值的时候,下游都会更新:
EZRMutableNode<NSNumber *> *nodeA = [EZRMutableNode value:@1];
EZRMutableNode<NSNumber *> *nodeB = [EZRMutableNode value:@2];
EZRNode<NSNumber *> *nodeC = [nodeA merge:nodeB];
// 首次合并会以最后有值的节点的值作为下游节点的初始值
nodeC.value; // <- 2
nodeA.value = @3;
nodeC.value; // <- 3
nodeB.value = @4;
nodeC.value; // <- 4
zip
拉链操作是这样的一种操作:它将多个节点作为上游,所有的节点的第一个值放在一个元组里,所有的节点的第二个值放在一个元组里……以此类推,以这些元组作为值的就是下游。它就好像拉链一样一个扣着一个:
EZRMutableNode<NSNumber *> *nodeA = [EZRMutableNode value:@1];
EZRMutableNode<NSNumber *> *nodeB = [EZRMutableNode value:@2];
EZRNode<EZTuple2<NSNumber *, NSNumber *> *> *nodeC = [nodeA zip:nodeB];
[[nodeC listenedBy:self] withBlock:^(EZTuple2<NSNumber *, NSNumber *> *tuple) {
NSLog(@"接收到 %@", tuple);
}];
nodeA.value = @3;
nodeA.value = @4;
nodeB.value = @5;
nodeA.value = @6;
nodeB.value = @7;
/* 打印如下:
接收到 <EZTuple2: 0x60800002b140>(
first = 1;
second = 2;
last = 2;
)
接收到 <EZTuple2: 0x60800002ac40>(
first = 3;
second = 5;
last = 5;
)
接收到 <EZTuple2: 0x600000231ee0>(
first = 4;
second = 7;
last = 7;
)
*/
其过程如下:
nodeA: -------1-------3-------4---------------6
| ╲ ╲
| ╲ ╲
| ╲ ╲
| ╲ ╲
nodeB: -------2-----------------+-----5--------+------7
| ╲ | ╲ |
↓ ↘ ↓ ↘ ↓
nodeC: -----(1,2)-------------------(3,5)-----------(4,7)