高阶变换

优质
小牛编辑
119浏览
2023-12-01

高阶总是给人一种十分复杂的感觉,然而在实际的使用中掌握它是有很大好处的。高阶数组是指代数组中每个元素也是数组的数组,所以高阶节点就是指代节点的值也是节点的节点。EZRNode<EZRNode *>就是一个这样的节点。下面会介绍高阶变换形式。

flatten

扁平变换就是把EZRNode<EZRNode<T> *>扁平到EZRNode<T>的一种变换,它将下游节点始终连接到上游节点的值上,例如:

EZRMutableNode<NSNumber *> *nodeA = [EZRMutableNode new];
EZRMutableNode<NSNumber *> *nodeB = [EZRMutableNode new];
EZRMutableNode<NSNumber *> *nodeC = [EZRMutableNode new];
EZRMutableNode<EZRNode<NSNumber *> *> *highOrderNode = [EZRMutableNode new];
EZRNode<NSNumber *> *flattenedNode = [highOrderNode flatten];
highOrderNode.value = nodeA;
nodeA.value = @1;
flattenedNode.value;                                                          // <- @1
highOrderNode.value = nodeB;
nodeB.value = @2;
flattenedNode.value;                                                          // <- @2
nodeA.value = @3;
flattenedNode.value;                                                          // <- @2,不再受 node A 影响了
highOrderNode.value = nodeC;
nodeC.value = @4;
flattenedNode.value;                                                          // <- @4

flattenMap

扁平映射变换相当于这样的一系列操作,它先将节点进行映射变换,并且映射的结果统统都是节点,最后再扁平变换一次。为什么我们需要扁平映射变换而不是简单的映射变换呢?是因为映射变换一定是一一对应的,假设上游节点有 10 个值的变化,映射变换后的下游节点一定也有 10 个值的变化。但如果我有 8 个或者 12 个值想要变换呢?那就需要扁平映射变换了;还有映射变换一定都是立即变换的,如果我们需要结果延迟变换,我们也需要扁平映射变换。例如下面的例子:

EZRMutableNode<NSNumber *> *node = [EZRMutableNode new];
EZRNode<NSNumber *> *flattenMappedNode = [node flattenMap:^EZRNode * _Nullable(NSNumber * _Nullable next) {
  NSInteger value = next.integerValue;
  EZRMutableNode<NSNumber *> *insideNode = [EZRMutableNode new];
  EZRNode<NSNumber *> *returnNode = [insideNode deliverOnMainQueue];
  while(value != 0) {
    insideNode.value = @(value % 10);
    value /= 10;
  }
  return returnNode;
}];
[[flattenMappedNode listenedBy:self] withBlock:^(NSNumber * _Nullable next) {
  NSLog(@"FlattenMappedNode 收到了 %@", next);
}];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  node.value = @12;
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  node.value = @0;
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  node.value = @27;
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  node.value = @9527;
});
/* 打印如下:
FlattenMappedNode 收到了 2
FlattenMappedNode 收到了 1
FlattenMappedNode 收到了 7
FlattenMappedNode 收到了 2
FlattenMappedNode 收到了 7
FlattenMappedNode 收到了 2
FlattenMappedNode 收到了 5
FlattenMappedNode 收到了 9
 */