<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Ahruman’s Webthing &#187; type system</title>
	<atom:link href="http://jens.ayton.se/blag/tag/type-system/feed/" rel="self" type="application/rss+xml" />
	<link>http://jens.ayton.se/blag</link>
	<description>Cocoa coding stuff, when I can be bothered.</description>
	<lastBuildDate>Thu, 25 Aug 2011 21:56:35 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Proposal: generics (and some other stuff) for Objective-C</title>
		<link>http://jens.ayton.se/blag/generics-for-objective-c/</link>
		<comments>http://jens.ayton.se/blag/generics-for-objective-c/#comments</comments>
		<pubDate>Mon, 05 Oct 2009 20:38:04 +0000</pubDate>
		<dc:creator>Jens Ayton</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[flamebait]]></category>
		<category><![CDATA[generics]]></category>
		<category><![CDATA[notc++]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[tl;dr]]></category>
		<category><![CDATA[type system]]></category>

		<guid isPermaLink="false">http://jens.ayton.se/blag/?p=78</guid>
		<description><![CDATA[Some time ago, Greg Parker asked the Twitternets what we’d like to see in a purely hypothetical Objective-C-without-the-C language. Someone — I believe it was Landon Fuller — pointed at an article about the Strongtalk type system for Smalltalk. I &#8230; <a href="http://jens.ayton.se/blag/generics-for-objective-c/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Some time ago, <a href="http://twitter.com/gparker/">Greg Parker</a> asked the Twitternets what we’d like to see in a purely hypothetical Objective-C-without-the-C language. Someone — I believe it was <a href="http://twitter.com/landonf">Landon Fuller</a> — pointed at an article about <a href="http://bracha.org/nwst.html">the Strongtalk type system for Smalltalk</a>. I quite like the idea of Objective-C-without-the-C (i.e., a language that is native to the Objective-C object system and runtime without the baggage of C), but after reading that article I found myself asking why we couldn’t do something similar in Objective-C.</p>
<p>I don’t think my random musings have much influence on the design of the language, but if I don’t write it down nobody’s going to know how nuts I am, so here’s a semi-concrete proposal for contextual types and generics for Objective-C. Since anyone even mentioning generics in the vicinity of Objective-C will inevitably be flamed for trying to turn it into C++, this is followed by an aside entitled <i>Why This is Not the Baby-eating Spawn of Bjarne Stroustrup</i>. (Nothing personal, Bjarne.)</p>
<p><span id="more-78"></span><br />
<h2 id="types-in-objc">Types in Objective-C</h2>
<p>A fundamental characteristic of Objective-C is that it has two separate type systems: the dynamic type system, which applies to objects, and the static type system, which applies to variables (which may or may not refer to objects).</p>
<p>As far as objects are concerned, the static type system is optional — you can refer to any object with the type <code class="objc code">id</code>, except when calling a method whose type may be ambiguous. The static type system is also advisory — it suggests to programmers, the compiler and other tools such as the <a href="http://developer.apple.com/tools/Xcode/">IDE</a> and <a href="http://clang-analyzer.llvm.org/">analyzer</a> what the class of an object may be at runtime, but doesn’t constrain the object. A variable of type <code>NSString&nbsp;*</code> may actually refer to an <code>NSArray</code> at runtime, and method calls will dynamically go to <code>NSArray</code>’s implementation.</p>
<p>My proposal deals only with the static type system. The idea is to provide information that helps the compiler and analyzer check your logic, and the IDE to provide better suggestions. This is done by replacing <code>id</code> with more specific static types in most of the situations it’s used in. The generated code is not affected in any way. The proposal does not introduce bondage and discipline on the language; the new types can always be cast away.</p>
<h2 id="contextual-types">Contextual Types</h2>
<p>By far the most common use of <code>id</code> is as the return type for methods that may return an instance of “this” class, or of the subclass it’s called on. The obvious examples are <code>+alloc</code> and <code>-init</code>.</p>
<p>The IDE and, I believe, the analyzer already use heuristics to determine the return type of <code>+alloc</code> and <code>-init</code>, but I propose formalizing this in code. It would look something like this:</p>
<pre class="objc code" id="contextual-example">@interface NSObject &lt;NSObject&gt;
{
    Class   isa;
}

+ (void)load;

+ (void) initialize;
- ([:Self]) init;

+ ([:Self]) new;
+ ([:Self]) allocWithZone:(NSZone *)zone;
+ ([:Self]) alloc;

// ...

+ ([:Superclass]) superclass;
+ ([:Class]) class;
- ([:Superclass]) superclass;
- ([:Class]) class;

@end</pre>
<p>When calling a class method, <code>[:Class]</code> resolves to the receiver (or, type-equivalently, a pointer to an instance the receiver’s metaclass), and <code>[:Self]</code> resolves to a pointer to an instance of the receiver. <code>[:Superclass]</code> resolves to the superclass of the receiver. For instances, they resolve as for class methods on the class of the instance.</p>
<p>I’m sure some people will object to the conceptual purity of this design, and possibly the names and syntax. The colon is a bit odd — it’s there to avoid ambiguity with generics (see <a href="#generics">below</a>). All of these are minor quibbles; the syntax would need to be reviewed if actually implementing it.</p>
<p>So what’s the point? Consider the following code:</p>
<pre class="objc code">NSString *s = [[NSArray alloc] init];</pre>
<p>As it stands, this is perfectly valid and doesn’t generate a compiler diagnostic. With the addition of contextual types it would, because:
<ul>
<li> The type of <code>+[NSArray alloc]</code> (inherited from <code>NSObject</code>) is <code>[:Self]</code>, which resolves to <code>NSArray&nbsp;*</code>.</li>
<li> The receiver of the <code>-init</code> is thus known to be an <code>NSArray</code>.</li>
<li> The type of <code>-[NSArray init]</code> (inherited from <code>NSObject</code>) is <code>[:Self]</code>, which again resolves to <code>NSArray&nbsp;*</code>.</li>
<li> Therefore, the right hand side of the assignment is of type <code>NSArray&nbsp;*</code>, and the assignment is invalid.</ul>
<p>If, for some reason, you really wanted to do that, you could use an explicit cast to get rid of the diagnostic.</p>
<h2 id="generics">Generics</h2>
<p>The other major use of <code>id</code> is for polymorphic collections. True polymorphic collections are great! But some of the time, you only want to put one kind of object in your collection, and would appreciate the computer doing the drudge work of checking that you didn’t put the wrong stuff in the wrong place.</p>
<p>From the perspective of the previous section, generics are a simple extension to contextual types. Instead of restricting you to <code>[:Self]</code> and the highly specialized <code>[:Class]</code> and <code>[:Superclass]</code>, you can provide one or more class names as a parameter to a type declaration. Example time again:</p>
<pre class="objc code" id="mythingholder-example">@interface MyThingHolder[ThingType = id] : NSObject
{
    [ThingType]     thing;
}

- ([:Self]) initWithThing:([ThingType])thing;

- (void) setThing:([ThingType])thing;
- ([ThingType]) thing;

// Or, for modernists:
@property (readonly, nonatomic) [ThingType] thing;

@end

// ...
MyThingHolder[NSString] *holder = [[MyThingHolder[NSString] alloc] initWithThing:@"foo"];
holder.thing = [NSNumber numberWithBool:MAYBE];      // Warning: type mismatch
holder.thing = (id)[NSNumber numberWithBool:MAYBE];  // OK. (an issue here would be inconsistent with general Objective-C behaviour.)

// Or, equivalently:
typedef MyThingHolder[NSString] MyStringHolder;
MyStringHolder *holder = [[MyStringHolder alloc] initWithThing:@"foo"];</pre>
<p>Some notes: the type parameter can only be a class, since specialized code is not generated for each type. (See <a href="#bjarnespawn">Why This is Not the Baby-eating Spawn of Bjarne Stroustrup</a> below.) Since the type parameter is always a class, I have made the <code>*</code> implicit. This is cleaner, but could well lead to confusion and is quite likely a bad idea. (If only I had a time machine…)</p>
<p>The type parameter has a default value, previously unheard of in Objective-C, so that you can ignore generics and create a “vanilla” <code>MyThingHolder</code> that works just like in traditional Objective-C. This provides an upgrade path for existing classes:</p>
<pre class="objc code" id="collections-example">@interface NSArray[Item &lt;NSObject&gt; = id &lt;NSObject&gt;] : NSObject &lt;NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration&gt;

- (NSUInteger) count;
- ([Item]) objectAtIndex:(NSUInteger)index;

@end

@interface NSArray[Item] (NSExtendedArray)

- (NSArray[Item] *) arrayByAddingObject:([Item])anObject;
- (NSArray[Item] *) arrayByAddingObjectsFromArray:(NSArray[Item] *)otherArray;
// ...
- (BOOL)containsObject:([Item])anObject;
// ...
<span id="decl-arrayWithObject">+ ([:Self[Item]]) arrayWithObject:([Item])anObject;</span>
// ...
<br/>
@interface NSDictionary[Key &lt;NSCopying, NSObject&gt; = id &lt;NSCopying, NSObject&gt;, Value &lt;NSObject&gt; = id &lt;NSObject&gt;] : NSObject &lt;NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration&gt;

- (NSUInteger) count;
- ([Value]) objectForKey:([Key])aKey;
- (NSEnumerator[Key] *)keyEnumerator;

@end

@interface NSDictionary[Key, Value] (NSExtendedDictionary)

- (NSArray[Key] *) allKeys;
- (NSArray[Key] *) allKeysForObject:([Value])anObject;
- (NSArray[Value] *) allValues;
// ...
- (BOOL) isEqualToDictionary:(NSDictionary[Key, Value] *)otherDictionary;
- (NSEnumerator[Value] *) objectEnumerator;
- (NSArray[Value] *) objectsForKeys:(NSArray[Key] *)keys notFoundMarker:([Value])marker;
// ...
- (void) getObjects:([Value] *)objects andKeys:([Key] *)keys;
// ...</pre>
<p>These examples introduce an additional concept: restrictions on type parameters, in this case protocol requirements. The other obvious type of restriction would be a superclass requirement, such as <code>[Type: NSString = NSString]</code>.</p>
<p>Using these genericized versions in the same manner as the existing versions would require no code changes – as long as you’re using them with objects that fulfil the protocol requirements, which already exist but aren’t explicit in code.</p>
<h2 id="type-conformance">Type Conformance</h2>
<p>A fundamental question for static type systems with inheritance is when implicit casts are allowed. There are subtleties here, some of which I probably haven’t considered, and I have a feeling I’ve considered some and then forgotten about them. The most obvious case is when the base type and each type parameter could be validly cast:</p>
<pre class="objc code" id="basic-implicit-casts-example">NSMutableArray[NSMutableString] *a = whatever;
NSMutableArray *b = a;            // OK, b is NSMutableArray[id &lt;NSObject&gt;]
NSMutableArray[NSString] *c = a;  // OK
a = b;                            // Not OK, implicit cast from NSMutableArray[NSString] to NSMutableArray[NSMutableString]
NSArray[NSMutableString] *d = a;  // OK
NSArray[NSString] *e = a;         // OK
id f = a;                         // OK
</pre>
<p>As indicated <a href="#mythingholder-example">above</a>, passing an <code>id</code> when a parameter type is expected is necessary for consistency with Objective-C in general:</p>
<pre class="objc code" id="id-implicit-cast-example">NSMutableArray[NSString] *a = whatever;
[a addObject:[NSNumber numberWithInt:42]];      // Type mismatch, assuming +numberWithInt: is declared to return [:Self]
[a addObject:(id)[NSNumber numberWithInt:42]];  // OK</pre>
<p>How about the case where a method returns an unadorned type?</p>
<pre class="objc code" id="legacy-example">@interface LegacyThing: NSObject
- (NSArray *) legacyListOfStrings;
@end

LegacyThing *l = whatever;
NSArray[NSString] *list = [l legacyListOfStrings];</pre>
<p>In order to minimize the burden of adopting generic syntax, I’d suggest explicitly permitting this, with an optional warning. (The non-generic equivalent, assigning an <code>id&nbsp;&lt;NSObject&gt;</code> to an <code>NSString&nbsp;*</code>, generates the somewhat unexpected warning <i>“type &#8216;id &lt;NSObject&gt;&#8217; does not conform to the &#8216;NSCopying&#8217; protocol”</i> in GCC and nothing in Clang. Assigning an <code>NSObject&nbsp;*</code> to an <code>NSString&nbsp;*</code> generates warnings in both. My proposal is that assigning a <code>T</code> to a <code>T[P]</code> should work without warning by default, even if the default type parameter is a class rather than <code>id</code> with or without protocols.)</p>
<h2 id="bjarnespawn">Why This is Not the Baby-eating Spawn of Bjarne Stroustrup</h2>
<p>Many Objective-C programmers are refugees from the blasted wasteland of C++, and will reflexively cringe at the similarity with templates:</p>
<pre class="objcpp code" id="cpp-vs-objc-example">std::vector&lt;Duck&gt; ducks;
Chicken chicken;
ducks.push_back(chicken);             // Error
ducks.push_back(*(Duck *)chicken);    // Horrible crash here or some time in the future, maybe.

NSArray[Duck] *ducks = [NSArray new];
Chicken *chicken = [Chicken new];
[ducks addObject:chicken];            // Warning: type mismatch
[ducks addObject:(Duck *)chicken];    // No problem, unless you call -quack on it.
</pre>
<p>While the difference should hopefully be clear by now, I’ll spell it out: in C++, <code>std::vector&lt;Duck&gt;</code> creates an entirely new class (with bits of <code>Duck</code> inlined into it). The Objective-C-with-generics version only provides hints to the compiler, so it can catch mistakes. It doesn’t stop you from putting chickens among your ducks, or make the duck array reject chickens at runtime, or generate a new array-of-chickens class.</p>
<p>In <a href="http://lists.apple.com/archives/objc-language/2003/Dec/msg00084.html">earlier discussions</a> of generics, it has been stated that this type of mistake is rare in practice and should be caught with unit tests. If you feel that way, you’re welcome to stick to your current approach, and the introduction of generics, as described, will not affect you.</p>
<p>To avoid ballooning side effects of generics, I’ve deliberately avoided suggesting generic functions and methods (i.e., ones whose return type is dependent on one or more argument types, independent of their class in the case of methods).</p>
<h2 id="one-last-thing">One Last Thing</h2>
<p>An effect of the above is that I want the language to contain types like <code>NSArray[NSMutableDictionary[NSString, NSSet[NSMutableArray[NSNumber]]]] *</code>. That doesn’t mean I want to spend my time <em>typing</em> <code>NSArray[NSMutableDictionary[NSString, NSSet[NSMutableArray[NSNumber]]]] *</code>, even with autocomplete. Fortunately, there exists a well-known solution to this problem: type inference.</p>
<p>If I access a member of an array of the aforementioned sesquipedalian type, I get an <code>NSMutableDictionary[NSString, NSSet[NSMutableArray[NSNumber]]] *</code>. What’s more, the compiler knows this. The benefit of static typing lies primarily in checking what I do with my dictionary, rather than checking that the item I retrieved is what I thought it was, so I should be able to ask it to type a variable appropriately.</p>
<p>I quite like C++1x’s solution of recycling the <code>auto</code> keyword for this use, but that would conflict with Objective-C’s goal of being a strict superset of C. There are various other choices, such as <code>var</code> or <code>any</code> — or maybe <code>ego</code>. In any case, type inference would lead to code like:</p>
<pre class="objcpp code" id="type-inference-example">typedef NSArray[NSMutableDictionary[NSString, NSSet[NSMutableArray[NSNumber]]]] MyHorribleNestedType;  // TODO: replace with sensible model classes.

MyHorribleNestedType *array = whatever;
var element = [array objectAtIndex:0];              // Type is inferred as NSMutableDictionary[NSString, NSSet[NSMutableArray[NSNumber]]]*
var subEntry = [NSArray arrayWithObject:@"bloop"];  // Type is inferred as NSArray[NSString]
[element setObject:subEntry forKey:@"moop"];        // Type mismatch: expected NSSet[NSMutableArray[NSNumber]], got NSArray[NSString]</pre>
<p>A subtlety here: the return type of <code>[NSArray arrayWithObject:@"bloop"]</code> (declared <a href="#decl-arrayWithObject">previously</a>) is <code>[:Self[Item]]</code>, which is inferred from the receiver (the <code>NSArray</code> class object) and argument to resolve to <code>NSArray[NSString]</code>. Instead of <code>typedef</code>ing <code>MyHorribleNestedType</code>, we could have constructed the type implicitly in the same way. like everything else in the proposal, this is optional; if you used <code>id</code> or explicit, unparameterized types in this example, the type mismatch would not be detected, but the generated code would be identical.</p>
<h2 id="summary">Summary</h2>
<ul>
<li> The <code>id</code> type is very powerful and flexible. However, most of the time you don’t need this flexibility, and type checking is helpful — this is why Objective-C has optional static type checking in the first place, and almost all Objective-C code opts in to it.</li>
<li> The proposal would not impose any new restrictions, or any new guarantees. It would only extend (optional) static type checking to cases which are currently not covered.</li>
<li> It would not involve any implicit code generation, and no runtime overhead.</li>
<li> Combined with type inference, it could catch errors without additional code.</li>
<li> There would be no new collections, and no implementation changes to existing ones other than updated type declarations. (Updated headers would work with the existing implementations.)</li>
<li> If you really don’t want static type checking, you can continue using <code>id</code> everywhere.</li>
<li> I mean it about the “optional”. The proposed change would have no effect unless adopted both by a class and its clients. A parameterized collection pointer can be cast to plain one at any time with no cost.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://jens.ayton.se/blag/generics-for-objective-c/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>

