MogKit 0.10

MogKit 0.10

测试测试过
Lang语言 Obj-CObjective C
许可协议 MIT
发布最新发布2015年3月

Mikael Hallendal维护。



MogKit 0.10

  • 作者
  • Mikael Hallendal

MogKit 是一个工具包,提供对集合和任何一系列值(如信号、通道等)的测试齐全且易于组合的转换。这些转换不依赖于基础值或数据结构,使得它们高度可重用。

与类似转换框架相比,MogKit 使用组合而不是链式调用进行操作,这意味着值仅迭代一次,而不是每次步骤迭代一次。

用例

有一些情况下使用 MogKit 可能是有意义的。以下是一个示例。

简单地转换数据

当您只想将一些数据(例如数组)转换成新数组时。

NSArray *array = @[@1, @2, @3];
NSArray *result = [array mog_transform:MOGMap(^id(NSNumber *number) {
    return @(number.intValue + 100);
});

// result is now @[@101, @102, @103]

或者处理一些数字并输出为字符串

NSArray *array = @[@1, @2, @3];

NSString *result = MOGTransform(array, MOGStringConcatReducer(@", "), MOGCompose(MOGMap(^id(NSNumber *val) {
    return @(val.intValue + 10);
}), MOGMap(^id(NSNumber *val) {
    return val.stringValue;
})));

// result = "11, 12, 13"

它也可以用于任何 NSObject

id object = @10;
NSArray *expected = @[@(-10), @0, @10];

NSArray *result = [object mog_transform:MOGFlatMap(^id(NSNumber *number) {
    return @[@(-number.intValue), @0, number];
}) reducer:MOGArrayReducer()];

// result = @[@(-10), @0, @10]

用于轻松实现一些转换函数

另一种情况是,当您有一些数据结构并想为它添加一个转换方法时,例如扩展 NSArray 并为其添加一个 filter 方法,您只需这样做:

@implementation NSArray (Filterable)

- (NSArray *)filter:(MOGPredicate)predicate
{
    return [self mog_transform:MOGFilter(predicate)];
}

@end

组合以创建新的转换

假设您想向 NSArray 添加一个 trim: 方法,该方法返回一个从开始和结束处去除 trimSize 个元素的新数组。

- (NSArray *)trim:(NSUInteger)trimSize 
{
    return [self mog_transform:MOGCompose(MOGDrop(trimSize), MOGTake(self.count - 2 * trimSize))];
}

非集合用例

使用 MogKit 并不仅仅是针对实现 NSFastEnumeration 的容器。您可以轻松地为任何想要转换值集的地方添加组合转换。以下是在 RACStream(来自 ReactiveCocoa)上添加 -mog_transform: 方法的一个示例,以便对所有流上的值应用传入的转换。这可以代替链接多个 RAC Streams 内置的转换。

@implementation RACStream (MogKit)

- (instancetype)mog_transform:(MOGTransformation)transformation
{
    Class class = self.class;

    MOGTransformation transformationWithMapToRAC = MOGCompose(transformation, MOGMap(^id(id val) {
        return [class return:val];
    }));

    MOGReducer *reducer = transformationWithMapToRAC(MOGArrayReducer());

    return [[self bind:^{
        return ^(id value, BOOL *stop) {
            id acc = reducer.reduce(reducer.initial(), value, stop);
            if (*stop) {
                acc = reducer.complete(acc);
            }
            return [class concat:acc];
        };
    }] setNameWithFormat:@"[%@] -mog_transform:", self.name];
}

@end

这可以随后用于将一个转换应用到通道中的所有值,如下所示:

NSNumberFormatter *currencyFormatter = [NSNumberFormatter new];
currencyFormatter.numberStyle = NSNumberFormatterCurrencyStyle;

MOGTransformation add100ToIntValuesAndFormatAsCurrency = MOGComposeArray(@[
    MOGFilter(StringIsValidInt()),
    MOGMap(^id(NSString *string) {
        return @([string intValue] + 100);
    }),
    MOGMap(^id(id val) {
        return [currencyFormatter stringFromNumber:val];
    })
]);

[[textField.rac_textSignal mog_transform:add100ToIntValuesAndFormatAsCurrency] subscribeNext:^(id x) {
    NSLog(@"Number plus 100 = %@", x);
}];

然后这个转换可以被重复使用,而且并不局限于 RACStream

已实现的转换

  • 映射
  • 过滤
  • 移除
  • 取出
  • TakeWhile
  • 取第N个
  • 丢弃
  • DROPWhile
  • 丢弃nil
  • 替换
  • 使用默认值替换
  • MapDropNil
  • Unique
  • Dedupe
  • Flatten
  • FlatMap
  • 分区By
  • 分区
  • Window

安装

子模块

您还可以将其作为子模块添加到您的项目中 https://github.com/mhallendal/MogKit.git 并在您的应用程序中包含项目文件。

如果您正在使用类似 -mog_transform: 这样的 Foundation 扩展,例如在 NSArray 上,请确保将 -ObjC 添加到您的应用程序的 其他链接器标志 中。

待办事项

  • Swift 支持(1.0 之后)

状态

API 还未锁定,因此可能在 1.0 发布之前略有变化。

这似乎与 Transducers 有关

对于熟悉 Transducers 的读者来说,这会感觉很熟悉,MogKit 是使用 Transducers 实现的,而 MOGTrasformation 实际上是将 MOGReducer 映射到 MOGReducer 的 transducers。

有关 Transducer 的简介,请参阅 Transducer 简介 和 Clojure 创造者 Clojure - Transducers 以及 Rich Hickey 的演讲 Rich Hickey