3

Haskell のような ReactiveCocoa 関数が必要ですbreak

break                   :: (a -> Bool) -> [a] -> ([a],[a])
break _ xs@[]           =  (xs, xs)
break p xs@(x:xs')
           | p x        =  ([],xs)
           | otherwise  =  let (ys,zs) = break p xs' in (x:ys,zs)

基本的に、最初のコンポーネントが一致しなかったすべてのアイテムであり、最初の一致の前にあるタプルを返します。2 番目のコンポーネントは、一致する項目とリストの末尾 (一致するかどうかに関係なく) です。

ReactiveCocoa への直訳は

- (RACTuple *)breakSequence:(RACSequence *)seq withBlock:(BOOL(^)(NSString *))matchBlock
{
    id head = [seq head];
    if (matchBlock(head)) {
        return [RACTuple tupleWithObjects:[RACSequence empty], seq, nil];
    } else {
        RACTuple *t = [self breakSequence:[seq tail] withBlock:matchBlock];
        return [RACTuple tupleWithObjects:[RACSequence sequenceWithHeadBlock:^id{
            return head;
        } tailBlock:^RACSequence *{
            return [t first];
        }], [t second], nil];
    }
}

明らかに動作しますが、 の再帰によりスタック オーバーフローが発生しますbreakSequence:seq withBlock:

ReactiveCocoa でこの機能を正常に実装するにはどうすればよいでしょうか?

ありがとう :-)

4

1 に答える 1

2

私の他のバージョンは少し醜いようですが、以下に投稿して動作します。@Justin Spahr-Summersが提案したものを使用します。

- (RACTuple *)betterBreakSequence:(RACSequence *)seq withBlock:(BOOL(^)(NSString *))matchBlock
{
    RACSequence *left = [seq takeUntilBlock:matchBlock];
    NSNumber *count = [left foldLeftWithStart:@0 reduce:^id(NSNumber *accumulator, id value) {
        return [NSNumber numberWithInteger:[accumulator integerValue]+1];
    }];
    RACSequence *right = [seq skip:[count integerValue]];
    return [RACTuple tupleWithObjects:left, right, nil];
}
于 2013-09-13T18:19:36.793 に答える