Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding complex block syntax

I'm a beginner to Objective C and iOS development, but a 13-year .NET veteran. I'm having a hard time mentally diagramming the following declaration, which came from the Programming with Objective C guide:

void (^(^a)(void (^) (void))) (void) = ...

It's used as an example of why one should use typedef to define blocks, but I want to understand what I'm looking at to better get a feel for block definition syntax in the first place.

Here's how I've diagrammed it so far:

enter image description here

Where I'm running into problems is that here is how I understand the basic syntax:

[return_val] (^[block_name]) ([block_args]) = ...

If that's the case, then what I have is a block that returns void and has no arguments, but is named (^a) (void (^) void). Meaning the name of my block, rather than being a straight string, is itself a block.

Clearly I'm missing something here. Can someone please shed some light on it? According to the site, it simplifies to this:

typedef void (^SimpleBlock) (void);
SimpleBlock (^complexBlock) (SimpleBlock) = ...

I'm just missing how.

Edit: The third void should have been in parentheses. I fixed that. It's wrong in the image, but I didn't feel like redoing the entire image just for that. :) If it turns out to be the source of my problem, I will fix it here.

like image 998
Ari Roth Avatar asked Feb 27 '14 01:02

Ari Roth


1 Answers

In your example you're missing some parentheses for the third void

void (^(^a)(void (^)(void)))(void)

Now let's break it down. The basic syntax to return a block from a function is:

void (^f())(void) { 
    return ^{}; 
}

In this example, the returned block takes no arguments and returns void.

Now let's build your example.

void     (^myBlock)(void);                       // Block returning void, taking no args
void     (^myBlock)(void (^)(void));             // Block returning void, taking block as arg
int      (^myBlock)(void (^)(void));             // Block returning int, taking block as arg
void (^  (^myBlock)(void (^)(void))  )(void);    // Block returning block, taking block as arg

I've aligned the central part in each line to make it easier to read. So the difficult part seems to be returning a block. In the last line we used the syntax I described earlier to return a block from a function.

Obviously the typedefs make it much easier to read.

EDIT:
Consider this example where, in the first line, i replace int for a block with the intuitive return syntax:

void (^ )(void) (^myBlock)(void (^)(void));          // Syntax we 'intuitively would use'
void (^         (^myBlock)(void (^)(void))  )(void); // Official syntax

I'm not 100% sure of what I'm about to say, but my suspicion is that the reason for this weird syntax is so that the parser in the compiler doesn't get confused. The first 'intuitive' syntax would make the compiler think that we have a block taking no arguments returning void, and the remaining characters would be considered syntax error.

In my opinion, syntax is something you don't question too much (you can criticize it, of course) because it's part of the design on a language, and we have to follow the rules (set by some hopefully smart engineers) for our code to compile.

like image 105
Merlevede Avatar answered Nov 12 '22 05:11

Merlevede