在Ruby中,在块内部调用return
甚至嵌套块将从最里面的包装方法转移控制和返回,我正在谈论proc。在一个Ruby lambda return
从块本身返回并且调用方法继续,这也是Objective-C阻塞工作的方式。
有没有办法在Objective-C中返回Ruby的proc语义w.r.t?我希望在块内返回以返回外部方法。
答案 0 :(得分: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
答案 1 :(得分:1)
我不熟悉Ruby,但是ObjC Block对其封闭方法施加控制的唯一方法是使该方法测试其返回值。
这可以很简单:
- (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
}