Ruby では、ブロック内またはネストされたブロック内で呼び出しreturn
を行うと、制御が転送され、最も内側のラッピング メソッド (proc) から戻ります。return
Ruby では、ブロック自体からラムダが戻り、呼び出しメソッドが続行されます。これは、Objective-C ブロックの動作方法でもあります。
Ruby の proc セマンティクス wrt を Objective-C で返す方法はありますか? ブロック内のリターンで外側のメソッドを返す必要があります。
Ruby では、ブロック内またはネストされたブロック内で呼び出しreturn
を行うと、制御が転送され、最も内側のラッピング メソッド (proc) から戻ります。return
Ruby では、ブロック自体からラムダが戻り、呼び出しメソッドが続行されます。これは、Objective-C ブロックの動作方法でもあります。
Ruby の proc セマンティクス wrt を Objective-C で返す方法はありますか? ブロック内のリターンで外側のメソッドを返す必要があります。
私は 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
}
簡単な答えは 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