the-swift-rogramming-language
.pdf
println(message)
}
}
let testNumber = 5
simpleAssert(testNumber % 2 == 0, "testNumber isn't an even number.") // prints "testNumber isn't an even number."
A function type can have a variadic parameter as the last parameter in its parameter type. Syntactically, a variadic parameter consists of a base type name followed immediately by three dots (...), as in Int.... A variadic parameter is treated as an array that contains elements of the base type name. For instance, the variadic parameter Int... is treated as Int[]. For an example that uses a variadic parameter, see Variadic Parameters.
To specify an in-out parameter, prefix the parameter type with the inout keyword. You can’t mark a variadic parameter or a return type with the inout keyword. In-out parameters are discussed in In-Out Parameters.
The type of a curried function is equivalent to a nested function type. For example, the type of the curried function addTwoNumbers()() below is Int -> Int -> Int:
func addTwoNumbers(a: Int)(b: Int) -> Int { return a + b
}
addTwoNumbers(4)(5) // Returns 9
The function types of a curried function are grouped from right to left. For instance, the function type Int -> Int -> Int is understood as Int -> (Int -> Int)—that is, a function that takes an Int and returns another function that takes and return an Int. For example, you can rewrite the curried function addTwoNumbers()() as the following nested function:
func addTwoNumbers(a: Int) -> (Int -> Int) { func addTheSecondNumber(b: Int) -> Int {
return a + b
}
return addTheSecondNumber
}
addTwoNumbers(4)(5) // Returns 9
G R A M M A R O F A F U N C T I O N T Y P E
function-type → type -> type
Array Type
The Swift language uses square brackets ([]) immediately after the name of a type as syntactic sugar for the named type Array<T>, which is defined in the Swift standard library. In other words, the following two declarations are equivalent:
let someArray: String[] = ["Alex", "Brian", "Dave"]
let someArray: Array<String> = ["Alex", "Brian", "Dave"]
In both cases, the constant someArray is declared as an array of strings. The elements of an array can be accessed using square brackets as well: someArray[0] refers to the element at index 0, "Alex".
As the above example also shows, you can use square brackets to create an array using an array literal. Empty array literals are written using an empty pair of square brackets and can be used to create an empty array of a specified type.
var emptyArray: Double[] = []
You can create multidimensional arrays by chaining multiple sets of square brackets to the name of the base type of the elements. For example, you can create a threedimensional array of integers using three sets of square brackets:
var array3D: Int[][][] = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
When accessing the elements in a multidimensional array, the left-most subscript index refers to the element at that index in the outermost array. The next subscript index to the right refers to the element at that index in the array that’s nested one level in. And so on. This means that in the example above, array3D[0] refers to [[1, 2], [3, 4]], array3D[0][1] refers to [3, 4], and array3D[0][1][1] refers to the value 4.
For a detailed discussion of the Swift standard library Array type, see Arrays.
G R A M M A R O F A N A R R A Y T Y P E
array-type → type [ ] array-type [ ]
Optional Type
The Swift language defines the postfix ? as syntactic sugar for the named type Optional<T>, which is defined in the Swift standard library. In other words, the following two declarations are equivalent:
var optionalInteger: Int?
var optionalInteger: Optional<Int>
In both cases, the variable optionalInteger is declared to have the type of an optional integer. Note that no whitespace may appear between the type and the ?.
The type Optional<T> is an enumeration with two cases, None and Some(T), which are used to represent values that may or may not be present. Any type can be explicitly declared to be (or implicitly converted to) an optional type. When declaring an optional type, be sure to use parentheses to properly scope the ? operator. As an example, to declare an optional array of integers, write the type annotation as (Int[])?; writing Int[]? produces an error.
If you don’t provide an initial value when you declare an optional variable or property, its value automatically defaults to nil.
Optionals conform to the LogicValue protocol and therefore may occur in a Boolean context. In that context, if an instance of an optional type T? contains any value of type T (that is, it’s value is Optional.Some(T)), the optional type evaluates to true. Otherwise, it evaluates to
false.
If an instance of an optional type contains a value, you can access that value using the postfix operator !, as shown below:
optionalInteger = 42
optionalInteger! // 42
Using the ! operator to unwrap an optional that has a value of nil results in a runtime error.
You can also use optional chaining and optional binding to conditionally perform an operation on an optional expression. If the value is nil, no operation is performed and therefore no runtime error is produced.
For more information and to see examples that show how to use optional types, see Optionals.
G R A M M A R O F A N O P T I O N A L T Y P E
optional-type → type ?
Implicitly Unwrapped Optional Type
The Swift language defines the postfix ! as syntactic sugar for the named type ImplicitlyUnwrappedOptional<T>, which is defined in the Swift standard library. In other words, the following two declarations are equivalent:
var implicitlyUnwrappedString: String!
var implicitlyUnwrappedString: ImplicitlyUnwrappedOptional<String>
In both cases, the variable unwrapped optional string. the !.
implicitlyUnwrappedString is declared to have the type of an implicitly Note that no whitespace may appear between the type and
You can use implicitly unwrapped optionals in all the same places in your code that you can use optionals. For instance, you can assign values of implicitly unwrapped optionals to variables, constants, and properties of optionals, and vice versa.
As with optionals, if you don’t provide an initial value when you declare an implicitly unwrapped optional variable or property, it’s value automatically defaults to nil.
Because the value of an implicitly unwrapped optional is automatically unwrapped when you use it, there’s no need to use the ! operator to unwrap it. That said, if you try to use an implicitly unwrapped optional that has a value of nil, you’ll get a runtime error.
Use optional chaining to conditionally perform an operation on an implicitly unwrapped optional expression. If the value is nil, no operation is performed and therefore no runtime error is produced.
For more information about implicitly unwrapped optional types, see Implicitly Unwrapped Optionals.
G R A M M A R O F A N I M P L I C I T LY U N W R A P P E D O P T I O N A L T Y P E
implicitly-unwrapped-optional-type → type !
Protocol Composition Type
A protocol composition type describes a type that conforms to each protocol in a list of specified protocols. Protocol composition types may be used in type annotations and in generic parameters.
Protocol composition types have the following form:
protocol< Protocol 1 , Protocol 2 >
A protocol composition type allows you to specify a value whose type conforms to the requirements of multiple protocols without having to explicitly define a new, named protocol that inherits from each protocol you want the type to conform to. For example, specifying a protocol composition type protocol<ProtocolA, ProtocolB, ProtocolC> is effectively the same as defining a new protocol ProtocolD that inherits from ProtocolA, ProtocolB, and ProtocolC, but without having to introduce a new name.
Each item in a protocol composition list must be either the name of protocol or a type alias of a protocol composition type. If the list is empty, it specifies the empty protocol composition type, which every type conforms to.
G R A M M A R O F A P R O T O C O L C O M P O S I T I O N T Y P E
protocol-composition-type → protocol < protocol-identifier-list opt > protocol-identifier-list → protocol-identifier protocol-identifier , protocol-identifier-list protocol-identifier → type-identifier
Metatype Type
A metatype type refers to the type of any type, including class types, structure types, enumeration types, and protocol types.
The metatype of a class, structure, or enumeration type is the name of that type followed by .Type. The metatype of a protocol type—not the concrete type that conforms to the protocol at runtime—is the name of that protocol followed by .Protocol. For example, the metatype of the class type SomeClass is SomeClass.Type and the metatype of the protocol
SomeProtocol is SomeProtocol.Protocol.
You can use the postfix self expression to access a type as a value. For example,
SomeClass.self returns SomeClass itself, not an instance of SomeClass. And SomeProtocol.self returns
SomeProtocol itself, not an instance of a type that conforms to SomeProtocol at runtime. You can use a dynamicType expression with an instance of a type to access that instance’s runtime type as a value, as the following example shows:
class SomeBaseClass {
class func printClassName() {
println("SomeBaseClass")
}
}
class SomeSubClass: SomeBaseClass { override class func printClassName() {
println("SomeSubClass")
}
meInstance: SomeBaseClass = SomeSubClass() meInstance is of type SomeBaseClass at compile time, but meInstance is of type SomeSubClass at runtime Instance.dynamicType.printClassName()
ts "SomeSubClass"
G R A M M A R O F A M E T A T Y P E T Y P E
metatype-type → type . Type type . Protocol
Type Inheritance Clause
A type inheritance clause is used to specify which class a named type inherits from and which protocols a named type conforms to. A type inheritance clause begins with a colon (:), followed by a comma-separated list of type identifiers.
Class types may inherit from a single superclass and conform to any number of protocols. When defining a class, the name of the superclass must appear first in the list of type identifiers, followed by any number of protocols the class must conform to. If the class does not inherit from another class, the list may begin with a protocol instead. For an extended discussion and several examples of class inheritance, see Inheritance.
Other named types may only inherit from or conform to a list of protocols. Protocol types may inherit from any number of other protocols. When a protocol type inherits from other protocols, the set of requirements from those other protocols are aggregated together, and any type that inherits from the current protocol must conform to all of those requirements.
A type inheritance clause in an enumeration definition may be either a list of protocols, or in the case of an enumeration that assigns raw values to its cases, a single, named type that specifies the type of those raw values. For an example of an enumeration definition that uses a type inheritance clause to specify the type of its raw values, see Raw Values.
G R A M M A R O F A T Y P E I N H E R I T A N C E C L A U S E
type-inheritance-clause → : type-inheritance-list
type-inheritance-list → type-identifier type-identifier , type-inheritance-list
Type Inference
Swift uses type inference extensively, allowing you to omit the type or part of the type of many variables and expressions in your code. For example, instead of writing var x: Int = 0, you can omit the type completely and simply write var x = 0—the compiler correctly infers that x names a value of type Int. Similarly, you can omit part of a type when the full type can be inferred from context. For instance, if you write let dict: Dictionary = ["A": 1], the compiler
infers that dict has the type Dictionary<String, Int>.
In both of the examples above, the type information is passed up from the leaves of the expression tree to its root. That is, the type of x in var x: Int = 0 is inferred by first checking the type of 0 and then passing this type information up to the root (the variable x).
In Swift, type information can also flow in the opposite direction—from the root down to the leaves. In the following example, for instance, the explicit type annotation (: Float) on the constant eFloat causes the numeric literal 2.71828 to have type Float instead of type Double.
let e = 2.71828 // The type of e is inferred to be Double. let eFloat: Float = 2.71828 // The type of eFloat is Float.
Type inference in Swift operates at the level of a single expression or statement. This means that all of the information needed to infer an omitted type or part of a type in an expression must be accessible from type-checking the expression or one of its subexpressions.
Expressions
In Swift, there are four kinds of expressions: prefix expressions, binary expressions, primary expressions, and postfix expressions. Evaluating an expression returns a value, causes a side effect, or both.
Prefix and binary expressions let you apply operators to smaller expressions. Primary expressions are conceptually the simplest kind of expression, and they provide a way to access values. Postfix expressions, like prefix and binary expressions, let you build up more complex expressions using postfixes such as function calls and member access. Each kind of expression is described in detail in the sections below.
G R A M M A R O F A N E X P R E S S I O N
expression → prefix-expression binary-expressions opt expression-list → expression expression , expression-list
Prefix Expressions
Prefix expressions combine an optional prefix operator with an expression. Prefix operators take one argument, the expression that follows them.
The Swift standard library provides the following prefix operators:
++ Increment -- Decrement ! Logical NOT ~ Bitwise NOT + Unary plus
- Unary minus
For information about the behavior of these operators, see Basic Operators and Advanced Operators.
In addition to the standard library operators listed above, you use & immediately before the name of a variable that’s being passed as an in-out argument to a function call expression. For more information and to see an example, see In-Out Parameters.
G R A M M A R O F A P R E F I X E X P R E S S I O N
prefix-expression → prefix-operatoropt postfix-expression prefix-expression → in-out-expression
in-out-expression → & identifier
Binary Expressions
Binary expressions combine an infix binary operator with the expression that it takes as its left-hand and right-hand arguments. It has the following form:
left-hand argument operator right-hand argument
The Swift standard library provides the following binary operators:
Exponentiative (No associativity, precedence level 160)
<< Bitwise left shift >> Bitwise right shift
Multiplicative (Left associative, precedence level 150)
* Multiply
/ Divide
% Remainder
&* Multiply, ignoring overflow &/ Divide, ignoring overflow
&% Remainder, ignoring overflow & Bitwise AND
Additive (Left associative, precedence level 140)
+ Add
- Subtract
&+ Add with overflow
&- Subtract with overflow
| Bitwise OR
^ Bitwise XOR
Range (No associativity, precedence level 135)
..
...
Half-closed range Closed range
Cast (No associativity, precedence level 132)
is
as
Type check Type cast
Comparative (No associativity, precedence level 130)
< Less than
<= Less than or equal > Greater than
>= Greater than or equal == Equal
!= Not equal
=== Identical !== Not identical
~= Pattern match
Conjunctive (Left associative, precedence level 120)
&& Logical AND
Disjunctive (Left associative, precedence level 110)
|| Logical OR
Ternary Conditional (Right associative, precedence level 100)
?: Ternary conditional
