blob: 5fcb25f7f408ad0b1f153a180bbfc6f0d79e471e [file] [log] [blame]
Sean Silvaf3a1ff32012-12-21 00:17:02 +00001====================
2Objective-C Literals
3====================
4
5Introduction
6============
7
8Three new features were introduced into clang at the same time:
9*NSNumber Literals* provide a syntax for creating ``NSNumber`` from
10scalar literal expressions; *Collection Literals* provide a short-hand
11for creating arrays and dictionaries; *Object Subscripting* provides a
12way to use subscripting with Objective-C objects. Users of Apple
13compiler releases can use these features starting with the Apple LLVM
14Compiler 4.0. Users of open-source LLVM.org compiler releases can use
15these features starting with clang v3.1.
16
17These language additions simplify common Objective-C programming
18patterns, make programs more concise, and improve the safety of
19container creation.
20
21This document describes how the features are implemented in clang, and
22how to use them in your own programs.
23
24NSNumber Literals
25=================
26
27The framework class ``NSNumber`` is used to wrap scalar values inside
28objects: signed and unsigned integers (``char``, ``short``, ``int``,
29``long``, ``long long``), floating point numbers (``float``,
30``double``), and boolean values (``BOOL``, C++ ``bool``). Scalar values
31wrapped in objects are also known as *boxed* values.
32
33In Objective-C, any character, numeric or boolean literal prefixed with
34the ``'@'`` character will evaluate to a pointer to an ``NSNumber``
35object initialized with that value. C's type suffixes may be used to
36control the size of numeric literals.
37
38Examples
39--------
40
41The following program illustrates the rules for ``NSNumber`` literals:
42
43.. code-block:: objc
44
45 void main(int argc, const char *argv[]) {
46 // character literals.
47 NSNumber *theLetterZ = @'Z'; // equivalent to [NSNumber numberWithChar:'Z']
48
49 // integral literals.
50 NSNumber *fortyTwo = @42; // equivalent to [NSNumber numberWithInt:42]
51 NSNumber *fortyTwoUnsigned = @42U; // equivalent to [NSNumber numberWithUnsignedInt:42U]
52 NSNumber *fortyTwoLong = @42L; // equivalent to [NSNumber numberWithLong:42L]
53 NSNumber *fortyTwoLongLong = @42LL; // equivalent to [NSNumber numberWithLongLong:42LL]
54
55 // floating point literals.
56 NSNumber *piFloat = @3.141592654F; // equivalent to [NSNumber numberWithFloat:3.141592654F]
57 NSNumber *piDouble = @3.1415926535; // equivalent to [NSNumber numberWithDouble:3.1415926535]
58
59 // BOOL literals.
60 NSNumber *yesNumber = @YES; // equivalent to [NSNumber numberWithBool:YES]
61 NSNumber *noNumber = @NO; // equivalent to [NSNumber numberWithBool:NO]
62
63 #ifdef __cplusplus
64 NSNumber *trueNumber = @true; // equivalent to [NSNumber numberWithBool:(BOOL)true]
65 NSNumber *falseNumber = @false; // equivalent to [NSNumber numberWithBool:(BOOL)false]
66 #endif
67 }
68
69Discussion
70----------
71
72NSNumber literals only support literal scalar values after the ``'@'``.
73Consequently, ``@INT_MAX`` works, but ``@INT_MIN`` does not, because
74they are defined like this:
75
76.. code-block:: objc
77
78 #define INT_MAX 2147483647 /* max value for an int */
79 #define INT_MIN (-2147483647-1) /* min value for an int */
80
81The definition of ``INT_MIN`` is not a simple literal, but a
82parenthesized expression. Parenthesized expressions are supported using
83the `boxed expression <#objc_boxed_expressions>`_ syntax, which is
84described in the next section.
85
86Because ``NSNumber`` does not currently support wrapping ``long double``
87values, the use of a ``long double NSNumber`` literal (e.g.
88``@123.23L``) will be rejected by the compiler.
89
90Previously, the ``BOOL`` type was simply a typedef for ``signed char``,
91and ``YES`` and ``NO`` were macros that expand to ``(BOOL)1`` and
92``(BOOL)0`` respectively. To support ``@YES`` and ``@NO`` expressions,
93these macros are now defined using new language keywords in
94``&LT;objc/objc.h&GT;``:
95
96.. code-block:: objc
97
98 #if __has_feature(objc_bool)
99 #define YES __objc_yes
100 #define NO __objc_no
101 #else
102 #define YES ((BOOL)1)
103 #define NO ((BOOL)0)
104 #endif
105
106The compiler implicitly converts ``__objc_yes`` and ``__objc_no`` to
107``(BOOL)1`` and ``(BOOL)0``. The keywords are used to disambiguate
108``BOOL`` and integer literals.
109
110Objective-C++ also supports ``@true`` and ``@false`` expressions, which
111are equivalent to ``@YES`` and ``@NO``.
112
113Boxed Expressions
114=================
115
116Objective-C provides a new syntax for boxing C expressions:
117
118.. code-block:: objc
119
120 @( <expression> )
121
122Expressions of scalar (numeric, enumerated, BOOL) and C string pointer
123types are supported:
124
125.. code-block:: objc
126
127 // numbers.
128 NSNumber *smallestInt = @(-INT_MAX - 1); // [NSNumber numberWithInt:(-INT_MAX - 1)]
129 NSNumber *piOverTwo = @(M_PI / 2); // [NSNumber numberWithDouble:(M_PI / 2)]
130
131 // enumerated types.
132 typedef enum { Red, Green, Blue } Color;
133 NSNumber *favoriteColor = @(Green); // [NSNumber numberWithInt:((int)Green)]
134
135 // strings.
136 NSString *path = @(getenv("PATH")); // [NSString stringWithUTF8String:(getenv("PATH"))]
137 NSArray *pathComponents = [path componentsSeparatedByString:@":"];
138
139Boxed Enums
140-----------
141
142Cocoa frameworks frequently define constant values using *enums.*
143Although enum values are integral, they may not be used directly as
144boxed literals (this avoids conflicts with future ``'@'``-prefixed
145Objective-C keywords). Instead, an enum value must be placed inside a
146boxed expression. The following example demonstrates configuring an
147``AVAudioRecorder`` using a dictionary that contains a boxed enumeration
148value:
149
150.. code-block:: objc
151
152 enum {
153 AVAudioQualityMin = 0,
154 AVAudioQualityLow = 0x20,
155 AVAudioQualityMedium = 0x40,
156 AVAudioQualityHigh = 0x60,
157 AVAudioQualityMax = 0x7F
158 };
159
160 - (AVAudioRecorder *)recordToFile:(NSURL *)fileURL {
161 NSDictionary *settings = @{ AVEncoderAudioQualityKey : @(AVAudioQualityMax) };
162 return [[AVAudioRecorder alloc] initWithURL:fileURL settings:settings error:NULL];
163 }
164
165The expression ``@(AVAudioQualityMax)`` converts ``AVAudioQualityMax``
166to an integer type, and boxes the value accordingly. If the enum has a
167`fixed underlying
168type <http://clang.llvm.org/docs/LanguageExtensions.html#objc_fixed_enum>`_
169as in:
170
171.. code-block:: objc
172
173 typedef enum : unsigned char { Red, Green, Blue } Color;
174 NSNumber *red = @(Red), *green = @(Green), *blue = @(Blue); // => [NSNumber numberWithUnsignedChar:]
175
176then the fixed underlying type will be used to select the correct
177``NSNumber`` creation method.
178
179Boxing a value of enum type will result in a ``NSNumber`` pointer with a
180creation method according to the underlying type of the enum, which can
181be a `fixed underlying
182type <http://clang.llvm.org/docs/LanguageExtensions.html#objc_fixed_enum>`_
183or a compiler-defined integer type capable of representing the values of
184all the members of the enumeration:
185
186.. code-block:: objc
187
188 typedef enum : unsigned char { Red, Green, Blue } Color;
189 Color col = Red;
190 NSNumber *nsCol = @(col); // => [NSNumber numberWithUnsignedChar:]
191
192Boxed C Strings
193---------------
194
195A C string literal prefixed by the ``'@'`` token denotes an ``NSString``
196literal in the same way a numeric literal prefixed by the ``'@'`` token
197denotes an ``NSNumber`` literal. When the type of the parenthesized
198expression is ``(char *)`` or ``(const char *)``, the result of the
199boxed expression is a pointer to an ``NSString`` object containing
200equivalent character data, which is assumed to be '\\0'-terminated and
201UTF-8 encoded. The following example converts C-style command line
202arguments into ``NSString`` objects.
203
204.. code-block:: objc
205
206 // Partition command line arguments into positional and option arguments.
207 NSMutableArray *args = [NSMutableArray new];
208 NSMutableDictionary *options = [NSMutableDictionary new];
209 while (--argc) {
210 const char *arg = *++argv;
211 if (strncmp(arg, "--", 2) == 0) {
212 options[@(arg + 2)] = @(*++argv); // --key value
213 } else {
214 [args addObject:@(arg)]; // positional argument
215 }
216 }
217
218As with all C pointers, character pointer expressions can involve
219arbitrary pointer arithmetic, therefore programmers must ensure that the
220character data is valid. Passing ``NULL`` as the character pointer will
221raise an exception at runtime. When possible, the compiler will reject
222``NULL`` character pointers used in boxed expressions.
223
224Availability
225------------
226
227Boxed expressions will be available in clang 3.2. It is not currently
228available in any Apple compiler.
229
230Container Literals
231==================
232
233Objective-C now supports a new expression syntax for creating immutable
234array and dictionary container objects.
235
236Examples
237--------
238
239Immutable array expression:
240
241.. code-block:: objc
242
243 NSArray *array = @[ @"Hello", NSApp, [NSNumber numberWithInt:42] ];
244
245This creates an ``NSArray`` with 3 elements. The comma-separated
246sub-expressions of an array literal can be any Objective-C object
247pointer typed expression.
248
249Immutable dictionary expression:
250
251.. code-block:: objc
252
253 NSDictionary *dictionary = @{
254 @"name" : NSUserName(),
255 @"date" : [NSDate date],
256 @"processInfo" : [NSProcessInfo processInfo]
257 };
258
259This creates an ``NSDictionary`` with 3 key/value pairs. Value
260sub-expressions of a dictionary literal must be Objective-C object
261pointer typed, as in array literals. Key sub-expressions must be of an
262Objective-C object pointer type that implements the
263``&LT;NSCopying&GT;`` protocol.
264
265Discussion
266----------
267
268Neither keys nor values can have the value ``nil`` in containers. If the
269compiler can prove that a key or value is ``nil`` at compile time, then
270a warning will be emitted. Otherwise, a runtime error will occur.
271
272Using array and dictionary literals is safer than the variadic creation
273forms commonly in use today. Array literal expressions expand to calls
274to ``+[NSArray arrayWithObjects:count:]``, which validates that all
275objects are non-``nil``. The variadic form,
276``+[NSArray arrayWithObjects:]`` uses ``nil`` as an argument list
277terminator, which can lead to malformed array objects. Dictionary
278literals are similarly created with
279``+[NSDictionary dictionaryWithObjects:forKeys:count:]`` which validates
280all objects and keys, unlike
281``+[NSDictionary dictionaryWithObjectsAndKeys:]`` which also uses a
282``nil`` parameter as an argument list terminator.
283
284Object Subscripting
285===================
286
287Objective-C object pointer values can now be used with C's subscripting
288operator.
289
290Examples
291--------
292
293The following code demonstrates the use of object subscripting syntax
294with ``NSMutableArray`` and ``NSMutableDictionary`` objects:
295
296.. code-block:: objc
297
298 NSMutableArray *array = ...;
299 NSUInteger idx = ...;
300 id newObject = ...;
301 id oldObject = array[idx];
302 array[idx] = newObject; // replace oldObject with newObject
303
304 NSMutableDictionary *dictionary = ...;
305 NSString *key = ...;
306 oldObject = dictionary[key];
307 dictionary[key] = newObject; // replace oldObject with newObject
308
309The next section explains how subscripting expressions map to accessor
310methods.
311
312Subscripting Methods
313--------------------
314
315Objective-C supports two kinds of subscript expressions: *array-style*
316subscript expressions use integer typed subscripts; *dictionary-style*
317subscript expressions use Objective-C object pointer typed subscripts.
318Each type of subscript expression is mapped to a message send using a
319predefined selector. The advantage of this design is flexibility: class
320designers are free to introduce subscripting by declaring methods or by
321adopting protocols. Moreover, because the method names are selected by
322the type of the subscript, an object can be subscripted using both array
323and dictionary styles.
324
325Array-Style Subscripting
326^^^^^^^^^^^^^^^^^^^^^^^^
327
328When the subscript operand has an integral type, the expression is
329rewritten to use one of two different selectors, depending on whether
330the element is being read or written. When an expression reads an
331element using an integral index, as in the following example:
332
333.. code-block:: objc
334
335 NSUInteger idx = ...;
336 id value = object[idx];
337
338it is translated into a call to ``objectAtIndexedSubscript:``
339
340.. code-block:: objc
341
342 id value = [object objectAtIndexedSubscript:idx];
343
344When an expression writes an element using an integral index:
345
346.. code-block:: objc
347
348 object[idx] = newValue;
349
350it is translated to a call to ``setObject:atIndexedSubscript:``
351
352.. code-block:: objc
353
354 [object setObject:newValue atIndexedSubscript:idx];
355
356These message sends are then type-checked and performed just like
357explicit message sends. The method used for objectAtIndexedSubscript:
358must be declared with an argument of integral type and a return value of
359some Objective-C object pointer type. The method used for
360setObject:atIndexedSubscript: must be declared with its first argument
361having some Objective-C pointer type and its second argument having
362integral type.
363
364The meaning of indexes is left up to the declaring class. The compiler
365will coerce the index to the appropriate argument type of the method it
366uses for type-checking. For an instance of ``NSArray``, reading an
367element using an index outside the range ``[0, array.count)`` will raise
368an exception. For an instance of ``NSMutableArray``, assigning to an
369element using an index within this range will replace that element, but
370assigning to an element using an index outside this range will raise an
371exception; no syntax is provided for inserting, appending, or removing
372elements for mutable arrays.
373
374A class need not declare both methods in order to take advantage of this
375language feature. For example, the class ``NSArray`` declares only
376``objectAtIndexedSubscript:``, so that assignments to elements will fail
377to type-check; moreover, its subclass ``NSMutableArray`` declares
378``setObject:atIndexedSubscript:``.
379
380Dictionary-Style Subscripting
381^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
382
383When the subscript operand has an Objective-C object pointer type, the
384expression is rewritten to use one of two different selectors, depending
385on whether the element is being read from or written to. When an
386expression reads an element using an Objective-C object pointer
387subscript operand, as in the following example:
388
389.. code-block:: objc
390
391 id key = ...;
392 id value = object[key];
393
394it is translated into a call to the ``objectForKeyedSubscript:`` method:
395
396.. code-block:: objc
397
398 id value = [object objectForKeyedSubscript:key];
399
400When an expression writes an element using an Objective-C object pointer
401subscript:
402
403.. code-block:: objc
404
405 object[key] = newValue;
406
407it is translated to a call to ``setObject:forKeyedSubscript:``
408
409.. code-block:: objc
410
411 [object setObject:newValue forKeyedSubscript:key];
412
413The behavior of ``setObject:forKeyedSubscript:`` is class-specific; but
414in general it should replace an existing value if one is already
415associated with a key, otherwise it should add a new value for the key.
416No syntax is provided for removing elements from mutable dictionaries.
417
418Discussion
419----------
420
421An Objective-C subscript expression occurs when the base operand of the
422C subscript operator has an Objective-C object pointer type. Since this
423potentially collides with pointer arithmetic on the value, these
424expressions are only supported under the modern Objective-C runtime,
425which categorically forbids such arithmetic.
426
427Currently, only subscripts of integral or Objective-C object pointer
428type are supported. In C++, a class type can be used if it has a single
429conversion function to an integral or Objective-C pointer type, in which
430case that conversion is applied and analysis continues as appropriate.
431Otherwise, the expression is ill-formed.
432
433An Objective-C object subscript expression is always an l-value. If the
434expression appears on the left-hand side of a simple assignment operator
435(=), the element is written as described below. If the expression
436appears on the left-hand side of a compound assignment operator (e.g.
437+=), the program is ill-formed, because the result of reading an element
438is always an Objective-C object pointer and no binary operators are
439legal on such pointers. If the expression appears in any other position,
440the element is read as described below. It is an error to take the
441address of a subscript expression, or (in C++) to bind a reference to
442it.
443
444Programs can use object subscripting with Objective-C object pointers of
445type ``id``. Normal dynamic message send rules apply; the compiler must
446see *some* declaration of the subscripting methods, and will pick the
447declaration seen first.
448
449Caveats
450=======
451
452Objects created using the literal or boxed expression syntax are not
453guaranteed to be uniqued by the runtime, but nor are they guaranteed to
454be newly-allocated. As such, the result of performing direct comparisons
455against the location of an object literal (using ``==``, ``!=``, ``<``,
456``<=``, ``>``, or ``>=``) is not well-defined. This is usually a simple
457mistake in code that intended to call the ``isEqual:`` method (or the
458``compare:`` method).
459
460This caveat applies to compile-time string literals as well.
461Historically, string literals (using the ``@"..."`` syntax) have been
462uniqued across translation units during linking. This is an
463implementation detail of the compiler and should not be relied upon. If
464you are using such code, please use global string constants instead
465(``NSString * const MyConst = @"..."``) or use ``isEqual:``.
466
467Grammar Additions
468=================
469
470To support the new syntax described above, the Objective-C
471``@``-expression grammar has the following new productions:
472
473::
474
475 objc-at-expression : '@' (string-literal | encode-literal | selector-literal | protocol-literal | object-literal)
476 ;
477
478 object-literal : ('+' | '-')? numeric-constant
479 | character-constant
480 | boolean-constant
481 | array-literal
482 | dictionary-literal
483 ;
484
485 boolean-constant : '__objc_yes' | '__objc_no' | 'true' | 'false' /* boolean keywords. */
486 ;
487
488 array-literal : '[' assignment-expression-list ']'
489 ;
490
491 assignment-expression-list : assignment-expression (',' assignment-expression-list)?
492 | /* empty */
493 ;
494
495 dictionary-literal : '{' key-value-list '}'
496 ;
497
498 key-value-list : key-value-pair (',' key-value-list)?
499 | /* empty */
500 ;
501
502 key-value-pair : assignment-expression ':' assignment-expression
503 ;
504
505Note: ``@true`` and ``@false`` are only supported in Objective-C++.
506
507Availability Checks
508===================
509
510Programs test for the new features by using clang's \_\_has\_feature
511checks. Here are examples of their use:
512
513.. code-block:: objc
514
515 #if __has_feature(objc_array_literals)
516 // new way.
517 NSArray *elements = @[ @"H", @"He", @"O", @"C" ];
518 #else
519 // old way (equivalent).
520 id objects[] = { @"H", @"He", @"O", @"C" };
521 NSArray *elements = [NSArray arrayWithObjects:objects count:4];
522 #endif
523
524 #if __has_feature(objc_dictionary_literals)
525 // new way.
526 NSDictionary *masses = @{ @"H" : @1.0078, @"He" : @4.0026, @"O" : @15.9990, @"C" : @12.0096 };
527 #else
528 // old way (equivalent).
529 id keys[] = { @"H", @"He", @"O", @"C" };
530 id values[] = { [NSNumber numberWithDouble:1.0078], [NSNumber numberWithDouble:4.0026],
531 [NSNumber numberWithDouble:15.9990], [NSNumber numberWithDouble:12.0096] };
532 NSDictionary *masses = [NSDictionary dictionaryWithObjects:objects forKeys:keys count:4];
533 #endif
534
535 #if __has_feature(objc_subscripting)
536 NSUInteger i, count = elements.count;
537 for (i = 0; i < count; ++i) {
538 NSString *element = elements[i];
539 NSNumber *mass = masses[element];
540 NSLog(@"the mass of %@ is %@", element, mass);
541 }
542 #else
543 NSUInteger i, count = [elements count];
544 for (i = 0; i < count; ++i) {
545 NSString *element = [elements objectAtIndex:i];
546 NSNumber *mass = [masses objectForKey:element];
547 NSLog(@"the mass of %@ is %@", element, mass);
548 }
549 #endif
550
551Code can use also ``__has_feature(objc_bool)`` to check for the
552availability of numeric literals support. This checks for the new
553``__objc_yes / __objc_no`` keywords, which enable the use of
554``@YES / @NO`` literals.
555
556To check whether boxed expressions are supported, use
557``__has_feature(objc_boxed_expressions)`` feature macro.