Skip to content

Instantly share code, notes, and snippets.

@nsforge
Created December 20, 2012 03:15
Show Gist options
  • Save nsforge/4342663 to your computer and use it in GitHub Desktop.
Save nsforge/4342663 to your computer and use it in GitHub Desktop.
A simple example of how Objective-C's instancetype would be useful in method arguments
@interface MyRequest : NSObject
// Variation One
- (void)startRequestWithCompletionBlock1:(void (^)(MyRequest *request))completionBlock;
// Variation Two
- (void)startRequestWithCompletionBlock2:(void (^)(id request))completionBlock;
// Variation Three
- (void)startRequestWithCompletionBlock3:(void (^)(instancetype request))completionBlock;
@end
...
@interface MyRequestSubclass : MyRequest
- (void)aSubclassMethod;
@end
...
// Usage
MyRequestSubclass *request;
[request startRequestWithCompletionBlock1:^(MyRequest *request){
MyRequestSubclass *requestAsSubclass = (MyRequestSubclass *)request; // typecast from MyRequest* to MyRequestSubclass* loses type safety
[requestAsSubclass aSubclassMethod];
}];
[request startRequestWithCompletionBlock2:^(MyRequestSubclass *request){ // typecast from id to MyRequestSubclass* loses type safety
[request aSubclassMethod];
}];
[request startRequestWithCompletionBlock3:^(instancetype request){ // typesafe
[request aSubclassMethod];
}];
@tkremenek
Copy link

In "Usage", what is 'instancetype' in:

[request startRequestWithCompletionBlock3:^(instancetype request){ // typesafe
[request aSubclassMethod];
}];

I can't tell what the calling context is here since those message expressions are free floating.

@nsforge
Copy link
Author

nsforge commented Dec 20, 2012

In the same way that instancetype means "an instance of the receiving class" when used as a return type, it would refer to "an instance of the receiving class" when used in an argument like this. So since the compiler can infer that request is of type MyRequestSubclass, instancetype would be translated into MyRequestSubclass *.

@tkremenek
Copy link

Got it. That's not what instancetype was really invented for. It was used to describe the type signatures of methods, not auto-deduce arguments. There's nothing here that would tie the use of "instancetype" to the "request" which is the receiver in the enclosing message expression.

Another problem is that C's expression parsing is bottom up. The block literal gets type checked before the enclosing message expression does. This means the expression for "request" gets type checked independently from the block literal. This is just fundamentally how C works.

@nsforge
Copy link
Author

nsforge commented Dec 20, 2012

Thanks for your feedback. When you say that that's "how C works", do you mean that that's how C compilers (including Clang) are currently implemented, or that this bottom up expression parsing and type checking is fundamental to the language itself? Would this sort of thing be implementable in Obj-C++ (just playing devil's advocate)?

@tkremenek
Copy link

The bottom up expression parsing and type checking is fundamental to the language itself. There are some cases where we can add limited type inference because it happens to work within the limitations of the language, e.g. instancetype or auto in C++11, but those are very limited cases. If you look at a language where type inference is a fundamental component, e.g. OCaml, the language parsing rules and type system are very different. In such a language, the type information can flow both up and down an expression tree, while in C this isn't possible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment