Reputation: 31486
I have a block defined like this:
CGPoint (^rotateOrderedPair)(CGFloat, CGFloat, CGFloat, CGFloat, CGFloat) = ^(CGFloat x, CGFloat y, CGFloat pivotX, CGFloat pivotY, CGFloat angle) {
CGFloat rotatedX = cos(angle) * (x - pivotX) - sin(angle) * (y - pivotY) + pivotX;
CGFloat rotatedY = sin(angle) * (x - pivotX) + cos(angle) * (y - pivotY) + pivotY;
return CGPointMake(rotatedX, rotatedY);
};
I'd like to ask why in the world do I have to write (CGFloat, CGFloat, CGFloat, CGFloat, CGFloat)
when there's a list of all the named arguments only a couple of characters later? Why such duplicity? I must be missing something obvious.
Upvotes: 2
Views: 126
Reputation: 104125
People usually typedef any non-trivial block, which makes this almost a non-issue:
typedef CGPoint (^XYPointTransform)(CGFloat, CGFloat, CGFloat, CGFloat, CGFloat);
And then:
XYPointTransform rotateOrderedPair =
^(CGFloat x, CGFloat y, CGFloat pivotX, CGFloat pivotY, CGFloat angle) {
// …
});
The typedef is also desirable from the point of code readability. Also, the signature in the declaration and definition doesn’t have to be exactly the same:
typedef void (^SomeBlock)(NSObject*);
SomeBlock foo = ^(id arg) {…};
This means that you’re not repeating exactly the same stuff twice and the possibility to pick a slightly different type in the actual block definition is sometimes handy.
I agree it would be nice to have some sort of type inference:
auto block = ^(/* a complex signature*/) {…};
This doesn’t exist, as far as I know.
Upvotes: 3
Reputation: 18253
The syntax of blocks is largely modeled on the syntax of C function pointers, so you should probably look for the rationale in that world.
Upvotes: 0