Xaree Lee
Xaree Lee

Reputation: 3387

How to implement recursive blocks?

I want to declare a block type which take one parameter that is the same block type. It's just like this:

typedef void (^BlockInBlock) (BlockInBlock block);

I know the declaration is not valid. But I wonder if there is any possible way to implement recursive block which take just one parameter that is the same block type.


I'm trying finding a way to implement aspect-oriented programming (AOP) in Objective-C using block. Here are my questions about how to implement that.

Further Question 1:

How to implement a variadic function which takes many Blocks I described above and is ended up with nil, and I could invoke that function with many blocks until meets nil? It would be like this:

@interface NSObject(AOP)
- (void) invokeBlockInBlock:(BlockInBlock) headBlock, ...{
    va_list blockList;
    va_start(blockList, headBlock);

    // Invoke recursive blocks here until the value of va_arg(blockList, BlockInBlock) is nil
    // it would be like: block1(self, block2(self, block3(self, block4(...))));

    va_end(blockList);
}
@end

Further Question 2:

What if the recursive block has a return value?


Additional Question about C language:

Is it possible to declare a C function which take one parameter that is a C function pointer, and that C function pointer's function also takes another C function pointer?

Upvotes: 8

Views: 4273

Answers (2)

holex
holex

Reputation: 24041

that may be similar you are looking for:

typedef void (^Block)(id);

literally, it will cause an infinite recursive loop:

Block _block;
_block = ^(Block block) {
    if (block) block(block);
};

_block(_block);

however the parameter could be any id not only the exact same Block, but it represents how you pass the same block as parameter for the same block.

so, that would be the idea.

Upvotes: 11

bbum
bbum

Reputation: 162712

It is much easier to do this by capturing the block in an __block reference. Actually, forward declaration of generic types in C are simply not supported. So, this may be the only solution?

__block void(^strawberryFields)();
strawberryFields = ^{ strawberryFields(); };
strawberryFields();

Note that if you are planning on dispatching that block asynchronously, you must copy it prior to assignment (this might no longer be necessary under ARC):

__block void(^strawberryFields)();
strawberryFields = [^{ strawberryFields(); } copy];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),
               strawberryFields);

Upvotes: 4

Related Questions