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)
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
Assignment (Right associative, precedence level 90)
= Assign
*= Multiply and assign /= Divide and assign
%= Remainder and assign
+= Add and assign
-= Subtract and assign
<<= Left bit shift and assign >>= Right bit shift and assign &= Bitwise AND and assign ^= Bitwise XOR and assign |= Bitwise OR and assign &&= Logical AND and assign ||= Logical OR and assign
For information about the behavior of these operators, see Basic Operators and Advanced Operators.
N O T E
At parse time, an expression made up of binary operators is represented as a flat list. This list is transformed into a tree by applying operator precedence For example, the expression 2 + 3 * 5 is initially understood as a flat list of five items, 2, +, `` 3``, *, and 5. This process transforms it into the tree (2 + (3 * 5)).
G R A M M A R O F A B I N A R Y E X P R E S S I O N
binary-expression → binary-operator prefix-expression binary-expression → assignment-operator prefix-expression binary-expression → conditional-operator prefix-expression binary-expression → type-casting-operator binary-expressions → binary-expression binary-expressions opt
Assignment Operator
The assigment operator sets a new value for a given expression. It has the following form:
expression = value
The value of the expression is set to the value obtained by evaluating the value. If the expression is a tuple, the value must be a tuple with the same number of elements. (Nested tuples are allowed.) Assignment is performed from each part of the value to the corresponding part of the expression. For example:
1 (a, _, (b, c)) = ("test", 9.45, (12, 3))
2 // a is "test", b is 12, c is 3, and 9.45 is ignored
The assignment operator does not return any value.
G R A M M A R O F A N A S S I G N M E N T O P E R A T O R
assignment-operator → =
Ternary Conditional Operator
The ternary conditional operator evaluates to one of two given values based on the value of a condition. It has the following form:
condition ? expression used if true : expression used if false
If the condition evaluates to true, the conditional operator evaluates the first expression and returns its value. Otherwise, it evaluates the second expression and returns its value. The unused expression is not evaluated.
For an example that uses the ternary conditional operator, see Ternary Conditional Operator.
G R A M M A R O F A C O N D I T I O N A L O P E R A T O R
conditional-operator → ? expression :
Type-Casting Operators
There are two type-casting operators, the as operator and the is operator. They have the following form:
expression as type
expression as? type
expression is type
The as operator performs a cast of the expression to the specified type. It behaves as follows:
If conversion to the specified type is guaranteed to succeed, the value of the expression is returned as an instance of the specified type. An example is casting from a subclass to a superclass.
If conversion to the specified type is guaranteed to fail, a compile-time error is raised.
Otherwise, if it’s not known at compile time whether the conversion will succeed, the type of the cast expresion is an optional of the specified type. At runtime, if the cast succeeds, the value of expression is wrapped in an optional and returned; otherwise, the value returned is nil. An example is casting from a superclass to a subclass.
class SomeSuperType {}
class SomeType: SomeSuperType {}
class SomeChildType: SomeType {}
let s = SomeType()
let x = s as SomeSuperType // known to succeed; type is SomeSuperType
let y = s as Int |
// known to fail; compile-time error |
let z = s as SomeChildType // might fail at runtime; type is SomeChildType?
Specifying a type with as provides the same information to the compiler as a type annotation, as shown in the following example:
let y1 = x as SomeType // Type information from 'as'
let y2: SomeType = x // Type information from an annotation
The is operator checks at runtime to see whether the expression is of the specified type. If so, it returns true; otherwise, it returns false.
The check must not be known to be true or false at compile time. The following are invalid:
"hello" is String
"hello" is Int
For more information about type casting and to see more examples that use the typecasting operators, see Type Casting.
G R A M M A R O F A T Y P E - C A S T I N G O P E R A T O R
type-casting-operator → is type as ? opt type
Primary expressions are the most basic kind of expression. They can be used as expressions on their own, and they can be combined with other tokens to make prefix expressions, binary expressions, and postfix expressions.
G R A M M A R O F A P R I M A R Y E X P R E S S I O N
primary-expression → identifier generic-argument-clause opt primary-expression → literal-expression primary-expression → self-expression
primary-expression → superclass-expression primary-expression → closure-expression primary-expression → parenthesized-expression primary-expression → implicit-member-expression primary-expression → wildcard-expression
Literal Expression
A literal expression consists of either an ordinary literal (such as a string or a number), an array or dictionary literal, or one of the following special literals:
Literal |
Type |
Value |
|
|
|
__FILE__ |
String |
The name of the file in which it appears. |
|
|
|
__LINE__ |
Int |
The line number on which it appears. |
|
|
|
__COLUMN__ |
Int |
The column number in which it begins. |
|
|
|
__FUNCTION__ |
String |
The name of the declaration in which it appears. |
|
|
|
Inside a function, the value of __FUNCTION__ is the name of that function, inside a method it is the name of that method, inside a property getter or setter it is the name of that property, inside special members like init or subscript it is the name of that keyword, and at the top level of a file it is the name of the current module.
An array literal is an ordered collection of values. It has the following form:
[ value 1 , value 2 , ... ]
The last expression in the array can be followed by an optional comma. An empty array literal is written as an empty pair of brackets ([]). The value of an array literal has type T[], where T is the type of the expressions inside it. If there are expressions of multiple types, T is their closest common supertype.
, opt
A dictionary literal is an unordered collection of key-value pairs. It has the following form:
[ key 1 : value 1 , key 2 : value 2 , ... ]
The last expression in the dictionary can be followed by an optional comma. An empty dictionary literal is written as a colon inside a pair of brackets ([:]) to distinguish it from an empty array literal. The value of a dictionary literal has type Dictionary<KeyType, ValueType>, where KeyType is the type of its key expressions and ValueType is the type of its value expressions. If there are expressions of multiple types, KeyType and ValueType are the closest common supertype for their respective values.
G R A M M A R O F A L I T E R A L E X P R E S S I O N
literal-expression → literal
literal-expression → array-literal dictionary-literal
literal-expression → __FILE__ __LINE__ __COLUMN__ __FUNCTION__
array-literal → [ array-literal-items opt ]
array-literal-items → array-literal-item , opt array-literal-item , array-literal-items array-literal-item → expression
dictionary-literal → [ dictionary-literal-items ] [ : ] dictionary-literal-items → dictionary-literal-item dictionary-literal-
item , dictionary-literal-items dictionary-literal-item → expression : expression
Self Expression
The self expression is an explicit reference to the current type or instance of the type in which it occurs. It has the following forms:
self
self. member name self[ subscript index ]
self( initializer arguments ) self.init( initializer arguments )
In an initializer, subscript, or instance method, self refers to the current instance of the type in which it occurs. In a static or class method, self refers to the current type in which it occurs.
The self expression is used to specify scope when accessing members, providing disambiguation when there is another variable of the same name in scope, such as a function parameter. For example:
class SomeClass {
var greeting: String
init(greeting: String) {
self.greeting = greeting
}
}
In a mutating method of value type, you can assign a new instance of that value type to self. For example:
struct Point {
var x = 0.0, y = 0.0
mutating func moveByX(deltaX: Double, y deltaY: Double) {
self = Point(x: x + deltaX, y: y + deltaY)
}
}
G R A M M A R O F A S E L F E X P R E S S I O N
self-expression → self self-expression → self . identifier self-expression → self [ expression ] self-expression → self . init
Superclass Expression
A superclass expression lets a class interact with its superclass. It has one of the following forms:
super. member name super[ subscript index ]
super.init( initializer arguments )
The first form is used to access a member of the superclass. The second form is used