So funktioniert die C-Syntax. Die Block-Syntax basiert auf der von function pointers, was auf Dennis Ritchies Idee hindeutet, dass "die Deklaration eines Dinges wie der Gebrauch dieses Dinges aussehen sollte".
Wenn Sie den „komplexen Block“ verwenden sind Sie definiert, und dann auch in der gleichen Zeile den zurück-Block zu nennen, würde es so aussehen:
complexBlock(void (^argBlock)(void){ /*...*/ })();
// ^Argument (a literal Block) to the main Block
// ^Invocation of the returned Block
ferner die Analyse von C-Deklarationen folgt eine sogenannte "right-left rule". Der erste Schritt ist "Finde die Kennung". Für Ihre Erklärung ist das complexBlock
.
void (^(^complexBlock)(void (^)(void)))(void);
// | ! | Found identifier: "complexBlock is..."
Dann schauen Sie nach rechts. Wir treffen eine schließende Klammer, also ist dies das Ende einer Deklaration "Einheit".
Gehen Sie zurück zum Anfang des aktuellen Teils und lesen Sie nach links bis eine öffnende Klammer. Wir finden den Caret, der einen Blocktyp angibt. Lesen Sie weiter links und suchen Sie eine öffnende Klammer, um diesen Teil der Deklaration zu schließen.
void (^(^ (void (^)(void)))(void);
// |! | "...a Block..."
Als nächstes gehen Sie wieder nach rechts. Hier finden wir eine öffnende Klammer, die den Beginn einer Parameterliste anzeigt. Überspringen Sie die Parameterliste, da Sie sich mit dem Rückgabetyp beschäftigen, aber er wird analysiert, wie eine eigenständige Deklaration sein würde.
void (^ (void (^)(void)))(void);
// | ! | "...taking something or other and returning..."
Nachdem wir nun die Parameterliste verbraucht haben:
void (^ )(void);
// | |
direkt weiter zu bewegen, und wir schlagen eine schließende Klammer:
void (^ )(void);
// | !
Also noch einmal zurück auf die Anfang des aktuellen Teils und gehe nach links, wo wir den Block caret finden.
void (^ (void);
// ! | "...a Block.."
Hier ist der Schlüsselteil für Ihre Frage zu dieser Erklärung:
links bewegt, wieder wir eine öffnende Klammer finden, so dass wir Rückgaberecht zu bewegen. Aus diesem Grund wird die Parameterliste des Rückgabe-Blocks am Ende der Deklaration eingefügt.
void ( (void);
// ! | Left parenthesis closes part of declaration,
// **now move rightwards again**
Nachdem alles durchgegangen ist, sollte der Rest selbstverständlich sein.
Übrigens hat die Seite, mit der ich über die Rechts-Links-Regel verbunden bin, ein paar Demonstrationen wie meine, von denen eine Funktionszeiger enthält. Sie können auch durch http://cdecl.org amüsiert sein, die eine Online-Implementierung eines Programms ist, das C-Deklarationen analysiert und Ihnen helfen kann, die wolligeren Varianten zu verstehen.
"Warum die zweite Syntax nicht ...", weil die Block-Syntax mit dem Rest der 45 Jahre alten C-Sprache übereinstimmen muss und jeder erwartet, dass die Syntax so ist, wie sie ist. Swift hat eine viel schönere Blocksyntax, wenn Sie die Syntax von Objective-C nicht mögen. –