1

Ruby では、ブロック内またはネストされたブロック内で呼び出しreturnを行うと、制御が転送され、最も内側のラッピング メソッド (proc) から戻ります。returnRuby では、ブロック自体からラムダが戻り、呼び出しメソッドが続行されます。これは、Objective-C ブロックの動作方法でもあります。

Ruby の proc セマンティクス wrt を Objective-C で返す方法はありますか? ブロック内のリターンで外側のメソッドを返す必要があります。

4

2 に答える 2

1

私は Ruby に詳しくありませんが、ObjC ブロックがそれを囲むメソッドを制御する唯一の方法は、そのメソッドがその戻り値をテストすることです。

これは次のように簡単です。

- (id)bloviate:(id (^)(void))bombast 
{
    // The method returns the results of the Block call;
    // thus, strictly speaking, the method returns when
    // the Block does.
    return bombast();
}

または、戻り値を確認して、メソッドから条件付きで返すこともできます。

- (id)elucidate:(BOOL (^)(id))explanation
{
    id obj = /* Get some object */;
    if( explanation(obj) ) {
        return obj;
    }
    // Else continue
}
于 2013-05-03T07:16:27.973 に答える
1

簡単な答えは NO です。ブロック内の return ステートメントは、ブロックからのみ返されます。以下に示すように、例外、ステートメント、およびマクロの組み合わせを使用して、洗練されていないものを作成でき@tryますが、最終的にはこれが何よりも混乱を招くと思います。

@interface MPReturnFromNestedBlockException : NSException
+ (void) returnExceptionWithResult:(id)result;
@end;

@implementation MPReturnFromNestedBlockException
+ (void) returnExceptionWithResult:(id)result
{
    MPReturnFromNestedBlockException *exception = (id)
        [self exceptionWithName:@"MPReturnFromMethodException"
                         reason:nil
                       userInfo:@{@"result":result}];
    [exception raise];
}
@end

#define abruptReturn(value)\
    ({ [MPReturnFromNestedBlockException returnExceptionWithResult:value]; })

#define blockMayReturnAbruptly(block)\
({\
    id result = nil;\
    @try { block(); }\
    @catch(MPReturnFromNestedBlockException *exception) {\
        result = exception.userInfo[@"result"];\
    }\
    result;\
})


int main (int argc, const char * argv[])
{
    @autoreleasepool {

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

        id value = blockMayReturnAbruptly(^{
            [numbers enumerateObjectsUsingBlock:^(id numA, NSUInteger index, BOOL *stop) {
                double a = [numA doubleValue];
                [numbers enumerateObjectsUsingBlock:^(id numB, NSUInteger index, BOOL *stop) {
                    double b = [numB doubleValue];
                    NSLog(@"%f x %f = %f", a, b, a*b);
                    if (a * b > 3)
                        abruptReturn(@(a*b));
                }];
            }];
        });

        NSLog(@"Result = %@", value);
    }
    return 0;
}

出力は次のとおりです。

1.000000 x 1.000000 = 1.000000
1.000000 x 2.000000 = 2.000000
1.000000 x 3.000000 = 3.000000
2.000000 x 1.000000 = 2.000000
2.000000 x 2.000000 = 4.000000
Result = 4
于 2013-05-03T07:13:58.317 に答える