Swift vs. Rust -- an Overview of Swift from a Rusty Perspective
Tags: swift, rust
Published: 2021-02-07 04:50:36

I first learned Swift in 2017, which for me was ages ago.  Back then it was at version 3.1.  I'm much more familiar with Rust, having been studying and using it now for about 8 months.  So when I went back to check out Swift again this week, I was really surprised by three things:

* Swift is now version 5.3 (two major versions!)
* Swift has finally been ported to Windows!
* Wow, Swift code sure looks a lot like Rust code!

I felt it might be fun to sit down and take notes while reading through the official [Swift Book] to "freshen up" on the language.  Being very much into Rust, I thought it would also be fun to include in my notes any comparisons I could draw between Swift and Rust.  It took a few days, and by the end I had quite a few notes written down.  So I decided to clean them up a bit and post them here!

The following is essentially a boiled-down comparison of Swift (version 5.3) with respect to Rust (edition 2018).  It follows along the chapters of the official [Swift Book].  Swift and Rust are very similar, so in general, if a specific point of comparison isn't mentioned here, it may be that the two languages are the same on that point, or "close enough" that I felt it didn't matter.  For example, `true` and `false` are the same for both Swift and Rust, and the syntax for various kinds of string literals are largely the same, so I didn't bother to write them down.  On the other hand, something not listed here could be something I didn't consider or know about at the time, in which case please let me know in the comments.  Thank you in advance!

If any information below is not completely verified or tested, a question-mark `?` punctuation will be used.  This is an open invitation to anyone who can verify the information (whether correct or incorrect) and provide evidence one way or another.

First of all, I found a few general topics of interest that weren't covered directly by the [Swift Book].  I grouped them together to list here:

* [Swift Package Manager](https://swift.org/package-manager/) &mdash; analogous to [cargo](https://doc.rust-lang.org/book/ch01-03-hello-cargo.html) in Rust, being a standard package management system for the language.
  * Note that unfortunately, as of the time of this writing, the Swift Package Manager is not available for Windows, so ad-hoc solutions based on tools such as CMake and Ninja are often used to construct build systems for Swift projects on Windows instead.
* [Swift Standard Library](https://developer.apple.com/documentation/swift/swift_standard_library) &mdash; this is tightly coupled with the compiler and facilitates the runtime and various types and functions essential to various aspects of the language.  It also provides support for features not covered by the book:
  * [Serialization](https://developer.apple.com/documentation/swift/swift_standard_library/encoding_decoding_and_serialization) &mdash; a set of protocols analogous to [serde](https://serde.rs/):
      * `Encodable` &mdash; `serde::Serialize`
      * `Decodable` &mdash; `serde::Deserialize`
      * `Encoder` &mdash; `serde::Serializer`
      * `Decoder` &mdash; `serde::Deserializer`
  * [C Interoperability](https://developer.apple.com/documentation/swift/swift_standard_library/c_interoperability) &mdash; various types and functions analogous to Rust's Foreign Function Interface (FFI).
* [Foundation](https://developer.apple.com/documentation/foundation) &mdash; this library originates from the Apple ecosystem (iOS, macOS, etc.) and is typically bundled with Swift due to providing access to essential operating system services, which in Rust are typically either built into the Rust standard library or are available from the Rust community's crate registry:
  * Date and time management
  * Localization (formatting of locale-aware string representations)
  * File system &mdash; creating, reading, writing, or examining files and directories
  * JSON encoding/decoding
  * Processes and threads
  * Networking
* [Dispatch](https://developer.apple.com/documentation/Dispatch) (also known as "Grand Central Dispatch" (GCD) &mdash; this library originates from the Apple ecosystem (iOS, macOS, etc.) and is typically bundled with Swift due to providing facilities for asynchronous programming, analogous to futures/async in Rust along with `futures-rs` and runtimes such as `tokio`, `async-std`, and `smol` available from the Rust community's crate registry.

[Swift Book]: https://docs.swift.org/swift-book/

## TL;DR &mdash; Overall Differences

I wrote quite a few notes down here, perhaps too many for some people.  So here's a summary of "what's important" when comparing Swift and Rust:

* Swift broadly categorizes types into "value" and "reference" types, hiding most of the implementation details of references from the programmer.  Rust makes references a first-class type and opens the entire type system up for the programmer, for better or worse.
* Swift supports class inheritance, while Rust does not.
* Swift uses the throwing and catching of exceptions for error handling, while Rust encourages the use of enumerated types to return "success or failure" variants from fallible operations.
* Most code constructs in Rust are expressions, whereas Swift has a more traditional separation between "statement" and "expression".
* Unlike Rust, Swift offers a comprehensive "properties" feature set (i.e. computed properties, property observers, projected values) similar to C#.
* Many language features that have their own keywords and syntax in Swift are handled through Rust's type system (i.e. optional types, boxing, references, operator overloading).
* Rust includes direct syntax for asynchronous programming (`async`, `await`), while Swift does not, relying on adjunct library facilities to support it.

### Opinion Section

I've tried to remain as objective as possible while writing this post.  However, there were a few subjective things I felt during this process.  Skip to the next section unless you're comfortable with a bit of biased opinions.

* Both languages aim to be general purpose systems programming languges. However, Swift has solid Apple roots and thus suffers from two main weaknesses:
  * Although Swift has strong corporate (Apple) backing, its overall community is weak in comparison to Rust.  Being relatively unencumbered, Rust has a more "well-rounded" base and robust community, as evidenced by:
      * Wider range of target platforms which support it.
      * Easier procedure to obtain, set up, and operate its toolchain.
      * Richer online environment for publishing and reusing libraries.
  * While Rust includes more advanced features such as threading, networking, and asynchronous coding directly in its standard library, Swift leverages adjunct libraries such as Foundation and GCD which were designed for Apple's ecosystem specifically.  Supporting other platforms entails "porting" these libraries after the fact or risking "crippling" the language for platforms which don't support the Apple libraries.
* Rust and Swift both aim to be "safe", referring to language design and compiler features which prevent and/or detect errors at compile-time.  However, they have fundamentally different approaches:
  * Rust has invested in the "borrow checker" approach where references are first-class types and the concept of "lifetimes" rises to the conscious level of the programmer.
      * Cost: more difficult for the programmer to learn, due to this approach being non-traditional and the syntax being more elaborate, requiring more practice and different ways of thinking about and designing code.
      * Gain: faster, more efficient code which can leverage both the stack and heap, allowing more sophisticated zero-copy designs and optimizations.
  * Swift took a traditional "pass by copy or reference" approach, with references being inherently reference-counted.
      * Gain: very similar to traditional programming languages, with semantics already familiar to most programmers, making the language easier to learn and use.
      * Cost: since the more traditional approach is taken, many of the more traditional drawbacks remain, such as unnecessary copying and indirection; although arguably the compiler has opportunities to optimize at least some of these away.
* In the realm of Object-Oriented Programming, Rust takes a heavy-handed approach encouraging the [Composition over inheritance](https://en.wikipedia.org/wiki/Composition_over_inheritance) principle by not supporting inheritance at all.  Although Swift supporting "protocols" (traits, interfaces) makes the language more "composition-friendly", it also includes class inheritance.  This makes Swift friendlier to programmers used to traditional object-oriented programming techniques using inheritance, at the cost of complicated rules for things such as initializers and access control.

Now, with all that out of the way, let's focus on language comparisons drawn by following along in the [Swift Book] and comparing to Rust.  In many places, I will abbreviate by showing Swift vs. Rust side-by-side with an "em (long) dash" (&mdash;) between.  Sorry if the formatting isn't too great; it works for me. `¯\_(ツ)_/¯`

## [The Basics](https://docs.swift.org/swift-book/LanguageGuide/TheBasics.html)

### Fundamental types

* `Int` &mdash; `isize`
* `UInt` &mdash; `usize`
* `Int8`, `Int16`, `Int32`, `Int64` &mdash; `i8`, `i16`, `i32`, `i64`
* `UInt8`, `UInt16`, `UInt32`, `UInt64` &mdash; `u8`, `u16`, `u32`, `u64`
* `Uint32.min`, `Uint32.max` &mdash; `u32::MIN`, `u32::MAX`
* `Double`, `Float` &mdash; `f64`, `f32`
  * Literals can be in hexidecimal: `0xFp-2` == 3.75
* `Bool` &mdash; `bool`

### Optionals

* `T?` &mdash; `Option<T>`
* `nil` &mdash; `None`
* `value == nil`, `value != nil` &mdash; `value.is_none()`, `value.is_some()`
* Optional binding:
  * `let possible_value: Int? = Int("123")` &mdash; `let possible_value = "123".parse().ok()`
  * `if let value = possible_value` &mdash; `if let Some(value) = possible_value`
* You can have many optional bindings in a single conditional:
  * `if let first = Int("4"), let second = Int("42"), first < second`
* Unwrapping values (`!` &mdash; `unwrap()`):
  * `let value: Int = Int("123")!` &mdash; `let value = "123".parse().ok().unwrap()` or just `let value = "123".parse().unwrap()`
* "Implicitly unwrapped optionals" are types that are unwrapped automatically if used in a non-optional context, but left optional otherwise:
  * `let x: Int! = Int("123")` <-- adding `!` to type makes it an implicitly unwrapped optional
  * `let y: Int = x` <-- implicitly unwrapped
  * `if let z = x` <-- left optional, tested in conditional

### Constants and Variables

* "Constant" is an immutable value, with the same syntax:
  * `let name = 10` &mdash; `let name = 10`
* "Variable" is a mutable value:
  * `var name = 10` &mdash; `let mut name = 10`
* You can have multiple declarations on a single line:
  * `var x = 0, y = 1, z = 2`
* Type annotations are the same, except you can define multiple values that share the same type annotation:
  * `var x, y, z: Int`
* Constant and variable names can contain almost any character:
  * `let π = 3.14159`
  * `let 你好 = "你好世界"`
  * `let 🐶🐮 = "dogcow"`
* No name shadowing allowed
* `print` is a combination `println!` and `print!` where it behaves like `println!` by default but you can set a custom `terminator` argument to `""` to be like `print!` or something else.
* Interpolation is intrinsically supported for strings:
  * `print("The answer is \(add(40, 2))")`
  * Note that the interpolation can be any expression, including literals and function calls.

### Comments

* Comments are the same, including ability to nest `/* */` style comments.

### Semicolons

* Swift only requires a semicolon at the end of a statement if another statement follows it on the same line.

### Type casts

* `(Double)name` &mdash; `name as f64`
* Some type casts return optionals:
  * `let possible_number: Int? = Int("123")`

### Type aliases

* `typealias AudioSample = UInt16` &mdash; `type AudioSample = u16`

### Tuples

* Tuples are the same except you can also name the parts of tuple literals:

```swift
let status = (statuscode: 200, description: "OK")
print("Status: \(status.statuscode) (\(status.description))")
```

### Error Handling

Here we have the first fundamental difference between Swift and Rust.  In Rust, errors are handled by representing them as values of the `Result::Error` type variant and returning them up the call chain through `Result` values.  In other words, successful return values and error return values essentially follow the same path out of function calls.  In Swift, errors are represented by values conforming to the `Error` protocol (trait) that are "thrown" at one point and "caught" (or not) somewhere up the call chain.  They follow a fundamentally separate path from successful return values.

A function that can throw an error must have the keyword `throws` placed in its declaration (before the body):

* `func can_throw() throws {` vs `func does_not_throw() {`

When calling such a function, you must prefix the call with the `try` keyword:

* `try can_throws()`

To automatically catch an error at the call site and convert it to an optional, use `try?` (equivalent to `Result::ok()` on the return value of a function in Rust):

* `let x: Int? = try? something()` &mdash; `let x: Option<isize> = something().ok()`

To automatically catch an error at the call site and terminate with a runtime error, use `try!` (equivalent to `Result::unwrap()` on the return value of a function in Rust):

* `let x: Int = try! something()` &mdash; `let x: isize = something().unwrap()`

Throw errors with the `throw` statement:

* `throw some_error`

Unless caught at the call site with `try?` or `try!`, errors "unwind the stack" or cause code execution to return out of functions until explicitly "caught". You catch errors outside the call site using a "do-catch" statement:

```swift
do {
    try something()
} catch some_error {
    handle_specified_error(some_error)
} catch {
    handle_unspecified_error(error)
}
```

Note that the special name `error` is available in the unspecified error handling block.

### Assertions and Preconditions

* `assert` and `precondition` are like the `assert!` macro, except that `assert` is only executed for a "Debug" build.
* `preconditionFailure` is essentially a `panic!`.

## [Basic Operators](https://docs.swift.org/swift-book/LanguageGuide/BasicOperators.html)

* Swift has the ternary operator `a ? b : c`, unlike Rust where you would instead use a conditional expression `if a { b } else { c }`.
* `String` type implements the `+` operator for concatenation; in Rust the `+` operator (or `String::push_str`) requires the right-hand side to be a slice.
* `Bool` type does not support comparison, unlike `bool` in Rust.
* "Nil-Coalescing Operator": `a ?? b` &mdash; `a.unwrap_or_else(|| b)`
  * Note that `b` is not evaluated unless `a` is `nil`, which is why it maps to `Option::unwrap_or_else` rather than `Option::unwrap_or`.
* Range operators
  * Closed range: `1...5` &mdash; `1..=5`
  * Half-open range: `1..<5` &mdash; `1..5`
  * One-sided range: `1...`, `...1` &mdash; `1..`, `..1`
  * There isn't a Swift equivalent of the Rust `RangeFull` (unbounded range `..`)?

## [Strings and Characters](https://docs.swift.org/swift-book/LanguageGuide/StringsAndCharacters.html)

* Swift strings are "composed of encoding-independent Unicode characters" and "built from Unicode scalar values", whereas in Rust `String` and `str` are UTF-8 encoded.
* A Swift `Character` is a single extended grapheme cluster (sequence of one or more Unicode scalars), whereas a Rust `char` is a single Unicode scalar.  For example, in Rust, `"café".chars().count()` is 5 and `"café".len()` is 6, whereas in Swift, `"café".count` is 4.
  * The letter `é` is a single grapheme cluster composed of the Unicode scalar "LATIN SMALL LETTER E" (U+0065), which is one byte when UTF-8 encoded, followed by the Unicode scalar "COMBINING ACUTE ACCENT" (U+0301), which is two bytes when UTF-8 encoded.
* In Swift you can modify characters in strings by concatenating Unicode scalars together.  For example, `"e" + "\u{301}" == "é"`.
* Swift `String` has an associated type `String.Index` representing the position of a `Character` in the `String`.
  * `String` methods `index(before:)`, `index(after:)`, and `index(_:offsetBy:)` are used with `String` properties `startIndex` and `endIndex` to construct `String.Index` values.
  * The `indices` property of `String` in Swift iterates over characters just like `str::chars` in Rust.
* Indexing or slicing a string returns a `Substring` which is similar to `str` (holds a reference to the `String` it was sliced from).
  * `let beginning = line[..<index]`
  * Converting `Substring` to `String` is a type cast
* You can encode `String` to UTF-8 or UTF-16 with the `utf8` or `utf16` properties which are `String.UTF8View` or `String.UTF16View` and are iterable as a sequence of `UInt8` or `UInt16`.
* You can get the Unicode scalar values of a `String` with the `unicodeScalars` property which is `UnicodeScalarView` and is iterable as a sequence of `UnicodeScalar`.
* Multi-line strings drop indented space, which Rust doesn't do inherently, but you can get the equivalent behavior if you use the
  [indoc](https://docs.rs/indoc) crate.
* Swift strings are value types, which are copied when passed to functions. There is no type distinction between mutable and immutable strings, like there is in Rust (with `String` being mutable and `str` (slice) being immutable).
  * Note that the book mentions, "Swift’s compiler optimizes string usage so that actual copying takes place only when absolutely necessary", which implies the implementation is perhaps closer to `Cow<'a, str>`?
* "Extended String Delimiters" are similar to "raw string literals" in that special characters can be placed in the string without invoking their effect. However, in Swift you can "manually invoke an effect" by adding a matching number of `#` pound signs following the `\\` backslash escape character:
  * `#"Line 1\nLine 2"#` &mdash; `r#"Line 1\nLine 2"#`
  * `##"Line 1\nLine 2"##` &mdash; `r##"Line 1\nLine 2"##`
  * `#"Line 1\#nLine 2"#` breaks the line and is equivalent to `"Line 1\nLine 2"` in Swift or Rust; no way to do this with a Rust raw string literal?

## [Collection Types](https://docs.swift.org/swift-book/LanguageGuide/CollectionTypes.html)

There are three primary collection types in Swift:

* `Array<T>` or `[T]` (shorthand) &mdash; `Vec<T>`
* `Set<T>` &mdash; `HashSet<T>`
* `Dictionary<Key, Value>` or `[Key: Value]` (shorthand) &mdash; `HashMap<K, V>`

The only ordered collection type is the `Array`.

* To order the keys of a `Set`, use the `sorted()` method, which returns an `Array` of the keys sorted in order.
* To order the contents of a `Dictionary`, use the `sorted()` method of the `keys` or `values` properties, which return an `Array` of the keys or values sorted in order.

The keys of `Set` and `Dictionary` need to be hashable, just as in Rust.  The protocol [`Hashable`](https://developer.apple.com/documentation/swift/hashable) in Swift is like the trait [`Hash`](https://doc.rust-lang.org/std/hash/trait.Hash.html) in Rust.

### Using Arrays

* `[Int32]()` &mdash; `Vec::<i32>::new()`
* `Array(repeating: 0.0, count: 3)` &mdash; `vec![0.0; 3]`
* `Array` supports the `+` and `+=` operators to concatenate and append, whereas in Rust you would have to start with the left-hand side and then either `append` or `extend` it.
* You can use subscript syntax to replace a value at a given index, just as in Rust:
  * `values[4] = "apples"`
* You can also use subscript syntax to splice:
  * `values[4...6] = ["apples", "oranges"]` &mdash; `values.splice(4..=6, ["apples", "oranges"].iter().cloned());`
* `removeLast()` &mdash; `Vec::pop`

### Using Sets

* `Set<Int32>()` &mdash; `HashSet::<i32>::new()`
* `let values: Set<Int> = [1, 2, 3]` &mdash; `let values = hashset!{1, 2, 3}` (using the [maplit](https://docs.rs/maplit/) crate)
* `count` &mdash; `HashSet::len`
* `substracting(_:)` &mdash; `HashSet::difference`
* `isStrictSubset(of:)` and `isStrictSuperset(of:)` are like `isSubset(of:)` and `isSuperset(of:)` except they return `false` if the sets are equal.

### Using Dictionaries

* `[Int32: String]()` &mdash; `HashMap::<i32, String>::new()`
* `[:]` &mdash; `HashMap::new()`
* `let dict = [1: "apples", 2: "oranges", 3: "bananas"]` &mdash; `let dict = hashmap!{1 => "apples", 2 => "oranges", 3 => "bananas"}` (using the [maplit](https://docs.rs/maplit/) crate)
* `count` &mdash; `HashMap::len`
* `dict.updateValue("answer", forKey: 42)` (or `dict[42] = "answer"` if the optional old value is not needed) &mdash; `dict.insert(42, "answer")`
* `dict[42]` &mdash; `dict.get(42)`
* `dict[42]!` &mdash; `dict[42]`

## [Control Flow](https://docs.swift.org/swift-book/LanguageGuide/ControlFlow.html)

* Control flow uses statement semantics, so they can't be used in expression contexts.  
  * For example, this is valid in Rust but not Swift: `let x = if y { 1 } else { 2 }` (one could use the ternary operator `y ? 1 : 2` instead)
  * Another consequence of this is that `break` statements cannot accept an argument.
* Swift has an additional "repeat-while" syntax similar to the "do-while" syntax in C, but lacks the `loop` infinite loop and `while let` syntax.
* Label names for loops (where a `continue` or `break` in a nested loop can jump out to a labelled outer loop) must begin with a quote `'` character in Rust, but not in Swift.
* A Swift `switch` is similar to a Rust `match` except:
  * The `case` keyword is present in front of each arm, similar to C.
  * The `default` keyword, without `case`, takes the place of `_` to match any cases not otherwise covered.
  * The body of each case must have at least one statement.
  * Alternative patterns are separated by comma `,` rather than pipe `|`.
  * Value binding in patterns requires placing the `let` keyword before the name to bind:
      * `case (let x, 0):` &mdash; `(x, 0) =>`
  * Swift uses the `where` keyword in place of `if` for "additional conditions" (called "match guards" in Rust).
      * `case let (x, y) where x == y:` &mdash; `(x, y) if x == y =>`
  * Swift has an additional control transfer statement `fallthrough` you can use as the last statement of a `case` in a `switch` in order to mimic the "fall through" behavior of a `switch` in C where the lack of a `break` causes execution to flow from the end of one case to the beginning of the next case.
* Swift has an additional "guard" syntax intended for use in "early exit" scenarios.  It looks simiar to an `if` statement, except `if` is replaced by `guard`, the `else` keyword is placed before the body, and any value bound to the condition (with `guard let`) is scoped to the block containing the guard. The body statements are only executed if the condition is `false`, and typically contain an "early exit" return.
* Conditional compilation in Swift is done using a special conditional you can use in `if` and `guard` statements, as opposed to the `cfg` attribute in Rust.
  * The only special conditional mentioned in the book for use in conditional compilation is the `#available` condition used to conditionally compile based on the target platform.

## [Functions](https://docs.swift.org/swift-book/LanguageGuide/Functions.html)

* `func` &mdash; `fn`
* If the entire body of the function is a single expression, the function implicitly returns that expression.  Rust supports this, but also allows there to be statements before the expression, which Swift doesn't support.
* Arguments are "labelled", and such argument labels are considered part of the function name.  This gives them an "Objective-C" flavor designed for compatibility with that language.
  * For example: `func speak(toPerson person: String, what speech: String)`
      * The name for this function overall is considered to be `speak(toPerson:what:)`.
  * If unspecified, the label is the same as the name:
      * `func speak(person: String, what speech: String)` is the same as `func speak(person person: String, what speech: String)`
  * A label may be omitted by replacing it with an underscore (`_`) in the function declaration.
      * `func speakTo(_ person: String, what speech: String)`
          * In this case the function name is considered to be `speakTo(_:what:)`
  * Labels not omitted must be used when calling the function.
      * For example: `speakTo("Frank", what: "Hello!")`
  * Although names must be unique, labels need not be (but usually are for readability).
* Arguments can have default values specified in the function declaration by adding after the type an equals sign (`=`) followed by a value.  If an argument has a default value, it can be omitted when calling the function.
* Functions support variadic parameters.  If the type of a parameter is followed by `...`, the actual type of the parameter will be an `Array` of the specified type, while callers provide the values for the array without using array syntax.
  * Note that a function can have at most one variadic parameter, but it doesn't necessary need to be the last parameter?

```swift
func average(_ numbers: Double...) -> Double {
    /* body omitted for brevity */
}
average(1, 2, 3)
average(1.2, 3.5)
```

* Parameters are constants (immutable) by default.
* Parameters are passed by value (copied, as in the `Copy` trait in Rust) if they are fundamental types, strings, or structures.  Otherwise, they are passed by reference.
* Placing the `inout` keyword before a parameter type in the function declaration gives the parameter a "copy-in copy-out" semantic (which may be optimized into "pass by mutable reference", but you shouldn't count on this).
  * When the function is called, the parameter is copied.
  * During the function call, the parameter is mutable and should be considered separate from the original value (although it may be optimized to be the same address in memory).
  * When the function returns, the parameter is copied back to caller, replacing the original value.
* For the purpose of identifying the type of a function with no return value, `Void` takes the place of `()` as the type returned.
* Functions passed as parameters are declared without any keyword like `func`:
  * `func useFunction(_ function: (Int) -> Int)` &mdash; `fn use_function(function: Fn(isize) -> isize)`
* Unlike in Rust, there is no distinction in Swift between "by-value" (`FnOnce`), "mutable" (`FnMut`), "immutable" (`Fn`), or "function pointer" (`fn`) closure/function types.
* A function declared inside another function is technically a closure in Swift (has access to all values in the scope of the outer function), whereas in Rust such a function is not a closure (although you could make the inner function a closure in Rust to do the same thing).

## [Closures](https://docs.swift.org/swift-book/LanguageGuide/Closures.html)

* `{(x: Int, y: Int) -> Int in x * y}` &mdash; `|x: isize, y: isize| x * y`
* `{x, y in x * y}` &mdash; `|x, y| x * y`
* Argument names can be omitted entirely if types can be implied; in this case special names formed by `$` followed by argument index represent each argument
  * `{$0 * $1}` &mdash; `|x, y| x * y`
* Operator methods are probably the shortest possible syntax for a closure.  For example, `names.sorted(by: >)` sorts `names` using the `>` operator of the type of the items in `names`.
* Swift has a "trailing closure" syntax where you can move a closure parameter to a block immediately after the parentheses of the function call.  For example, `names.sorted(by: { $0 > $1 })` can be written as `names.sorted() { $0 > $1 }` instead.
  * The argument label for the first trailing closure is omitted.  If there are additional trailing closures, they follow the first trailing closure body and are proceeded by their argument labels.
  * If there are no arguments besides the trailing closure(s), the parentheses of the function call itself can be omitted as well.  For example: `names.sorted{ $0 > $1 }`
* Closures capture constants and variables from the surrounding context by reference.  As an optimization, the compiler may capture them by value instead, if they are not mutated by the closure or any code executed after the closure is created.
* Closures are reference types (may be obvious, but the book has a special section to emphasize this point).
* Closures can have a "capture list" where you explicitly control what values from the surrounding context are captured and how they are captured.
  * If present, the capture list comes first inside the opening curly brace (`{`) of the closure.
  * Inside square brackets, place a comma-separated list of items, where each item is a value to capture, optionally with the `weak` or `unowned` keyword in front to specify whether the reference should be weak or not counted at all (respectively).  Each value may also be bound to a name local to the closure.  For example:
      * `[self]` &mdash; capture value `self` by strong reference
      * `[weak self]` &mdash; capture value `self` by weak reference
      * `[weak delegate = self.delegate]` &mdash; capture value `self.delegate` by weak reference named `delegate`.
* A closure which "escapes" a function (called after the function returns) must be marked with `@escaping` before the closure's type in the function parameter list.
* Marking a closure parameter with `@autoclosure` before the closure's type in a function parameter list allows you to call the function and pass an expression that is automatically wrapped by a closure.  In other words, the expression passed to the function is "lazily evaluated", or not evaluated until and unless the closure is called by the function.

## [Enumerations](https://docs.swift.org/swift-book/LanguageGuide/Enumerations.html)

* When listing variants of enums, each line must begin with the `case` keyword.
  * Multiple variants may be declared per line, if they are comma-separated.
* The syntax for specifying a variant is `TypeName.variant` or just `.variant` if `TypeName` can be inferred.
* By adding `: CaseIterable` after the name of an enum in its declaration (in other words, specifying that the enum conforms to the `CaseIterable` protocol), Swift will add an `allCases` property which is a collection of all the variants.
* Enum values can be printed without implementing any protocol.
* In a `switch` on an enum, the associated values (if any) are bound to names by placing `let` followed by a name in the case pattern, or by placing a single `let` immediately following the `case` keyword.
* As an alternative to associated types, enums can handle "raw values" by adding a colon followed by raw value type after the name of the enum.  Each variant gets a corresponding raw value, which can be either assigned by default or assigned by providing a literal value after the variant name with an equals sign (`=`) between the name and value.  Raw value types can be characters, strings, integers, or floating-point numbers.  Variants not assigned an explicit raw value get one assigned according to their position and type:
  * Integers default to `0` for the first variant or the value of the previous variant plus one.
  * Strings default to the name of the variant itself.
  * Raw value type enums automatically get an initializer method that takes a raw value of the proper type and returns an optional enum value (the variant that corresponds to the given raw value, or `nil` if no there is no corresponding variant for the raw value).
* An enum variant can have an associated value that has the same enum type, as long as the variant is marked with the `indirect` keyword before the `case` of the variant.  This causes Swift to add indirection to the variant, just as you would have to do manually using `Box<T>` in Rust to achieve the same thing.

## [Structures and Classes](https://docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html)

* Both structures and classes in Swift are like structures in Rust.
* Classes have additional capabilities that structures don't have:
  * Inheritance (not directly supported in Rust at all)
  * Type casting
  * Deinitializers (analogous to the `Drop` trait in Rust)
  * Reference counting (analogous to the `Rc` and `Arc` types in Rust)
      * Structures (and enumerations) are "value types", meaning they are copied when assigned or passed to functions.
      * Classes are "reference types" meaning they behave as if implicitly wrapped in an `Rc`/`Arc`, where a reference is added when assigned or passed to functions, and the value is only deallocated when the reference count goes to zero.
* Use the `class` keyword in place of `struct` to make a class, similar to C++.
* Fields are defined (and may be initialized as well) in the type definition using the same syntax as variable declaration and assignment, including the ability to let the compiler infer types (unlike in Rust where each field's type must be explicitly defined, and initialization happens in a method or explicit structure instantiation).
* To distinquish equality from identity, Swift defines the operator `===` (and inverse `!==`) for references, where `===` is like `Arc::ptr_eq`, returning `true` if the operands refer to the same value.
* Swift references are automatically dereferenced when used; there is no syntax for "dereferencing" or for creating a new reference (other than assigning a reference or passing it to a function).  In other words, references are not first class types in Swift?

## [Properties](https://docs.swift.org/swift-book/LanguageGuide/Properties.html)

* Properties are either "stored" (as in Rust) or "computed".
  * A stored property marked with the `lazy` keyword before its declaration is not calculated until the first time it's used.
* A "computed" property can be defined for classes, structures, and enum types.  They are declarated similarly to properties with accessors in C# classes:
  * After the type name of the property is a block containing two inner blocks, one with `get` before it and the other with `set` before it.  These inner blocks are like functions called when the property is read or written, respectively.
  * The `get` block is expected to compute the value of the property and return it using a `return` statement.
      * A shorthand syntax is supported where the inner block of the `get` is a single expression.  In this case, that expression is evaluated to compute the value of the property, without a need for an explicit `return` statement.
  * The `set` block gets an value argument which is the expression assigned to the property.  There are two ways of defining this value:
      * By placing a name in parentheses between `set` and its code block, the value is given that name.
      * Otherwise, an implicit value named `newValue` is defined within the code block.
  * A read-only computed property is declared by dropping the `get` keyword, keeping the block of statements that would have come after `get`, and dropping the `set` keyword and its code block entirely.
* Swift supports "property observers" which are like functions called automatically whenever a property's value is set.  They may be added for stored properties as well as inherited computed properties (for non-inherited computed properties, you put the observer code directly in the property's "setter").
  * Property observers are added in a syntax similar to computed properties, with a block after the type and default value (if any) of the property, and inner blocks proceeded by the `willSet` and `didSet` keywords.
      * Both `willSet` and `didSet` and their code blocks are optional.  You can have one or both.
      * The `willSet` block has the same syntax as the `set` block (besides the keyword being different) and is called just before the property is set.
      * The `didSet` block has the same syntax as the `set` block except for the keyword and the default name of the argument provided to it being `oldValue` rather than `newValue`.  The `didSet` block is called just after the property is set.  The argument provided is the value the property had before it was set.
* Swift supports "property wrappers" which are special structures which represent properties and provide reusable code for the getters and setters of properties.
  * They are declared like normal structures but with `@propertyWrapper` in front.
  * They must expose a computed property named `wrappedValue` which provides the getter and setter for the wrapped property.
  * Property wrappers are applied to a computed property by prefixing the computed property with the name of the property wrapper with `@` in front (in other words, the name of the property wrapper turned into an attribute).
  * Initializers provided with property wrappers can be used to set the initial value of wrapped properties.
      * A wrapped property with no default value provided uses the `init()` initializer to initialize the property.
      * A wrapped property with a single value assigned to it uses the `init(wrappedValue:)` initializer to initialize the property.
      * Other initializers may be used by expanding the property wrapper attribute applied to the computed property to look like a function call, with labels and values provided that need to match one of the `init` initializers of the property wrapper.
  * They support "projected values" which are exposed as if the type containing the computed property had a second read-only computed property with the same name but prefixed by a dollar sign (`$`).  To add a projected value, the property wrapper declares its own property named `projectedValue` which provides the projected value.
* Computed properties and property observers can also be applied to global and local variables, which act like stored properties of structures.
  * Global variables act as if declared with the `lazy` keyword, in that they are not initialized until used for the first time.
* Swift supports "type properties" which are properties applying to types themselves (rather than values of a type).  These have the `static` keyword added before the property declaration.
  * Type properties are accessed through the type name itself, as if the type was a structure.

## [Methods](https://docs.swift.org/swift-book/LanguageGuide/Methods.html)

* Classes, structures, and enums can have methods.
* Instance methods are like functions declared in an `impl` block for a Rust type, except in Swift they are placed inside the type declaration itself, similar to how methods are declared in C++.
* Methods have access to the properties of their instance as if the names of the properties were within the scope of the method (similar to C++).
* A special implicit property `self` is available to methods, bound to the instance itself.  This is similar to the `this` value in C++ methods, and similar to `self` in Rust `impl` functions, except that it's implicit (as if declared as `&mut self` for classes or `&self` for structures and enums).
* To make `self` mutable for structures and enums, add the `mutating` keyword in front of the `func` keyword in the method declaration.
  * Note that you cannot call a "mutating" method on a constant structure or enum.
  * You can assign to `self` in a "mutating" method to replace the value with a new one.  This can be useful, for example, in enums for changing the variant.
* Type methods are like instance methods except the methods are called on the type itself, `self` refers to the type, not any specific value of the type, and any unqualified method or property names used in the method refer to the other type-level methods and properties of the type, rather than of any specific value of the type.
  * To declare a type method, add the keyword `static` in front of the method declaration.
* Class methods are like type methods, except they can be overridden in subclasses (and therefore may only be declared in classes).
  * To declare a class method, add the keyword `class` in front of the method declaration.
* Unlike Rust, in Swift you can have "overloaded" methods, or multiple methods with the same name but different types for parameters and/or return value.

## [Subscripts](https://docs.swift.org/swift-book/LanguageGuide/Subscripts.html)

* Swift "subscripts" are similar to the `Index` and `IndexMut` traits in Rust, allowing types to define special methods to be used if instances are indexed.
* The syntax of subscripts are a mix of function and computed property syntax.
  * Their declarations begin like functions except there is no `func` keyword, and the name is replaced by the `subscript` keyword.
  * They have `get` and `set` blocks in the body, similar to computed properties.
      * The `get` block corresponds to `Index::index` in Rust.
      * The `set` block corresponds to `IndexMut::index_mut` in Rust, except rather than returning a reference, it takes a value to be assigned, like a computed property setter.
* Subscripts can have multiple parameters, which are separated by commas both in the declaration and usage of the subscripts.
* A "type subscript" or "class subscript" is similar to a "type method" or "class method", respectively.  They're declared like a normal subscript, but with the `static` or `class` keyword in front of the declaration.  They enable indexing the overall type itself.

## [Inheritance](https://docs.swift.org/swift-book/LanguageGuide/Inheritance.html)

As inheritance is entirely foreign to Rust, this section will compare inheritance in Swift to inheritance in C++.

* Properties can be overridden to provide custom getters, setters, or observers for any inherited property.  An overridden property has the `override` keyword added similarly to an overriden method.
  * A read-only property may be overridden to be read-write.
  * A read-write property *may not* be overridden to be read-only.
* Properties and methods can be prevented from being overridden by adding the `final` keyword before their declarations in the superclass.
* An entire class can be prevented from being subclassed by adding the `final` keyword before its declaration.
* There are no "pure virtual" classes or methods in Swift.  Use "protocols" instead.
* "Multiple inheritance" (a subclass having two or more superclasses) is not supported.

## [Initialization](https://docs.swift.org/swift-book/LanguageGuide/Initialization.html)

* An "initializer" is similar to a C++ constructor; declared like a method, named `init`, but without the `func` keyword, and called when the type is used like a function, in order to ensure all properties of a new instance are initialized.  This is roughly analogous to the `new` function convention and `Default` trait in Rust, except that the instance is provided through the implicit `self` value rather than being returned.
* Default initializers are generated for each struct/class type (as long as all fields have default values and the type doesn't provide at least one explicit initializer).
* Memberwise initializers are also generated for each struct/class type (if they don't provide at least one explicit initializer).  They are the same as the default initializers except they take parameters with labels matching the names of the fields of the type.
* All properties of a value must be initialized by the time the initializer returns.  Properties may be initialized either in the property declaration itself, or in the code of the initializer.
* Initializers can call other initializers of the same type, to reduce duplication of code.
* Classes can have special initializers called "convenience initializers" (declared by adding the `convenience` keyword before the initializer).  These are not used implicitly by subclasses, but can be used for direct initialization of values, as well as by other initializers.
* Superclass initializers are called from subclass initializers through the name `super`, as in: `super.init()`.
* Initializers that are not "convenience" are referred to as "designated initializers".
* Swift enforces rules about how initializers can call other initializers in the inheritance hierarchy of a class:
  * Designated initializers must call a designated initializer from its immediate superclass, if any.
  * Convenience initializers must call another initializer from the same class.
  * Convenience initializers must "ultimately" (either directly or through another convenience initializer) call a designed initializer.
* Swift enforces rules about property initialization within the inheritance hierarchy of a class:
  * A designated initializer must ensure all non-inherited properties are initialized before calling a superclass designated initializer.
  * A designated initializer cannot assign to an inherited property until after calling a superclass designated initializer.
  * A convenience initializer must call a designated initializer before assigning to any property.
  * An initializer cannot call any methods of the type, read any property values, or refer to `self` as a value until after all superclass designated initializers have returned.
* An initializer can be marked fallable by using `init?` instead of `init` for the initializer name.
  * Such an initializer can use a `return nil` statement to indicate that initialization failed.
  * Calling such an initializer produces an optional value.
* By using `init!` instead of `init?`, an initializer produces an instance that is "implicitly unwrapped".
* A superclass can require all subclasses to provide an initializer of a certain form (parameters) by declaring its own initializer with that form and adding the `required` keyword in front.
* Default property values can be specified as closure or function calls, in order for those default values to be computed during initialization.

## [Deinitialization](https://docs.swift.org/swift-book/LanguageGuide/Deinitialization.html)

* Swift supports "deinitializers" for classes (not structures or enums).  They are analogous to the `Drop` trait in Rust.
* The deinitializer is declared like an initializer with no parameters, but with the name `deinit` instead of `init`.

## [Optional Chaining](https://docs.swift.org/swift-book/LanguageGuide/OptionalChaining.html)

Optional chaining in Swift refers to using the question-mark (`?`) operator in an expression that calls a property or method of an optional value.  It's analogous to `Option::map` or `Option::and_then` in Rust.

For example, in Swift::

```swift
let result: SomeType? = value.property?.change()
```

This is analogous to the following in Rust:

```rust
let result: Option<SomeType> = value.property().map(Property::change)
```

The way to think of it is the call chain consists of intermediate optional values, and stops if at any point an intermediate value is `nil` (analogous to `None` in Rust).

Optional chaining which ends in an assignment results in that assignment only happening if the whole left-hand side expression is not `nil`.

Swift automatically "flattens" the evaluated values in optional chaining, whereas in Rust it's up to the developer to select either `Option::map` or `Option::and_then` depending on whether an optional value or non-optional value is returned at any given point to avoid "nesting" options.  In other words, in Swift:

* If a non-optional value is evaluated in an optional chain, it will become optional.
* If an optional value is evaluated in an optional chain, it remains optional (it does not become something like `Option<Option<T>>` for example).

## [Error Handling](https://docs.swift.org/swift-book/LanguageGuide/ErrorHandling.html)

Error handling was mostly already covered in [The Basics](#the-basics). Essentially, Swift uses an "exception throw/catch" approach for handling errors, whereas Rust uses a "return success/failure" approach instead.

Swift also supports a special code block called a "defer statement".  By adding the `defer` keyword in front of a nested block of code, the compiler will execute the code inside the block just before the enclosing scope is exited.  This is useful for "cleanup" code that needs to be run in the event of an error being thrown causing the current scope to unwind.  Defer statements are executed in the reverse of the order in which they're written.

## [Type Casting](https://docs.swift.org/swift-book/LanguageGuide/TypeCasting.html)

Two additional operators are needed in the Swift type system when dealing with classes, due to the nature of class inheritance:

* The `is` operator is used to determine at runtime if a value is of a certain subclass type.  This is similar to `Any::is` in Rust.
  * For example: `let isApple: Bool = (fruit is Apple)`
* The `as?` and `as!` operators are used to "downcast" a value to a subclass type.  The `as?` operator returns an optional subclass value.  The `as!` operator returns a subclass value or triggers a runtime error if the value isn't of the subclass type.  These are similar to `Any::downcast_ref` in Rust.

## [Nested Types](https://docs.swift.org/swift-book/LanguageGuide/NestedTypes.html)

Swift, unlike Rust, supports "nested types", which are types declared within the scope of another type.  They are merely syntactic sugar for the purpose of grouping types or limiting types used in implementations from being exposed in the public interface.

## [Extensions](https://docs.swift.org/swift-book/LanguageGuide/Extensions.html)

Swift supports adding computed properties, methods, initializers, subscripts, nested types, and type protocol implementations to existing types through a special syntax.  The existing type name is prefixed with the `extension` keyword and followed by a block containing the new properties, methods, etc. inside.  This is all syntactic sugar giving the appearance of extending a type, when in actuality the new functionality is added alongside the existing type.  It's similar to "extension traits" in Rust?

## [Protocols](https://docs.swift.org/swift-book/LanguageGuide/Protocols.html)

Protocols in Swift are analogous to "traits" in Rust.

* Protocols are declared using the `protocol` keyword, followed by the protocol name, followed by a block containing declarations of the requirements of any type implementing the protocol.
* Property requirements are specified like computed properties without statement blocks.
* Method requirements are specified like methods but without bodies.
* As with superclasses, protocols include the `required` keyword with initializer requirements.
* Types implementing protocols list the protocols after the type name.  If more than one protocol is implemented, they are all listed together separated by commas.
* Swift protocols can be used as types for values.  Such values are analogous to "trait objects" in Rust, allocated on the heap and always handled by reference-counted pointer, although Swift hides most of these details from the programmer.
* Generic types in Swift can conditionally conform to a protocol by listing constraints on the type, similar to trait bounds in Rust.
* Swift provides automatic ("synthesized") implementations of the `Equatable`, `Hashable`, and `Comparable` protocols for types that adhere to certain rules specific to those protocols.
  * `Equatable` &mdash; `PartialEq`
  * `Hashable` &mdash; `Hash`
  * `Comparable` &mdash; `PartialOrd`
* Protocols can be restricted for use by classes only by inheriting from the special `AnyObject` protocol.
* Protocol composition is a way to combine multiple protocol requirements for a value of some concrete type.  It's specified similarly to how multiple trait bounds are specified in Rust, except that `&` is used to separate multiple kprotocols rather than the `+` used to separate multiple traits in Rust trait bounds.
* The `is`, `as?`, and `as!` operators work with procotols the same way as they do for subclasses.
* For interoperability with Objective-C, Swift allows protocols marked with the `@objc` attribute to contain "optional requirements", or specifications of properies or methods which may or may not be implemented for a type.
  * Such requirements have the keywords `@objc` and `optional` at the front.
  * An "optionally required" method is essentially an "optional function".  The `?` operator can be used in a call to such a method, to use "optional chaining" to test at runtime to see if the method is available on the value before calling it:  `someOptionalMethod?(someArgument)`
* Default implementations for protocol requirements can be specified using property extensions.  This makes such requirements essentially "optional" for types to implement; if a type implements it, that implementation is used, otherwise the default implementation is used.

## [Generics](https://docs.swift.org/swift-book/LanguageGuide/Generics.html)

* An extension declaration for a generic type does not repeat the declaration of the type parameters.
* Generic associated types are declared in protocols using the `associatedtype` keyword (in Rust you would just use the `type` keyword). When implementing such a protocol, the associated type is inferred, unlike in Rust where you have assign it to the associated type placeholder in the implementation of the generic.
  * `struct Stack<Element>: Container` &mdash; `type Item = Element`
* Associated type constraints are declared along with the associated type in the protocol, whereas in Rust you would apply the constraints in the implementation blocks or methods where those constraints are needed.
* Swift supports type constraint specifications on generic type parameters using `where` clauses similar to Rust; however, the clauses can specify that types be equal, in addition to that types implement certain protocols.  The equivalent of requiring type equality in Rust is to use "associated type bindings".  For example:
  * Swift: `func foo<I: Iterator>(it: I) where I.Item == Foo`
  * Rust: `fn foo<I>(it: I) where I: Iterator<Item=Foo>`
* Extensions of generics may also add type constraint specifications of their own.

## [Opaque Types](https://docs.swift.org/swift-book/LanguageGuide/OpaqueTypes.html)

The `some` keyword in Swift is used similarly to the `impl` keyword, particularly in the return value position, to stand for "some type that implements a protocol (trait)" where the compiler can determine the actual concrete type:

* `-> some Shape` &mdash; `-> impl Shape`

## [Automatic Reference Counting](https://docs.swift.org/swift-book/LanguageGuide/AutomaticReferenceCounting.html)

* Weak references: `weak var tenant: Person?` &mdash; `let mut tenant: Weak<Person>`
* An "unowned reference" has the `unowned` keyword before the declaration of a non-optional value.  Such a reference does not participate in automatic reference counting, but unlike a weak pointer it's not "optional" (cannot be `nil`).  A "dangling" unowned reference causes a runtime error if accessed. There is no clear analogue to this in Rust; `*const T`, and `*mut T` come close to realizing this concept but don't match precisely?
* An "unowned optional reference" is the same as an "unowned reference" except the value is an optional type.  This makes it analogous to a `*const T` or `*mut T` in Rust?

## [Memory Safety](https://docs.swift.org/swift-book/LanguageGuide/MemorySafety.html)

Essentially, Swift does a limited form of "borrow checking" by detecting "memory conflicts" where there is some overlap (multi-borrow) in referencing values.  The following examples are provided by the book:

* In-out parameters: passing a value for an `inout` parameter to a function which accesses the same value
* "Self": passing a value for an `inout` parameter to a method of the same value
* Passing two parts of the same tuple as `inout` parameters to a function

## [Access Control](https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html)

* A "module" in Swift is a "crate" in Rust.
* Access levels are relative to module and source file.
* Swift has finer-grained access control than Rust:
  * `open` &mdash; like `public`, but allows subclassing in other modules.
  * `public` &mdash; essentially `pub` in Rust
  * `internal` &mdash; essentially `pub(crate)` in Rust
  * `fileprivate` &mdash; analogous to `pub(self)` in Rust, if in the top-level module for a source file.
  * `private` &mdash; analogous to `private` in C++; not applicable to Rust.

## [Advanced Operators](https://docs.swift.org/swift-book/LanguageGuide/AdvancedOperators.html)

* `&+` &mdash; `{integer}::overflowing_add`
* `&-` &mdash; `{integer}::overflowing_sub`
* `&*` &mdash; `{integer}::overflowing_mul`
* `static func +` &mdash; `std::ops::Add`
* `static prefix func -` &mdash; `std::ops::Neg`
* `static postfix func !` is for postfix operators (no equivalent in Rust?).
* You can define custom operators in Swift, such as: `static prefix func +++`.
  * For custom infix operators, you can define what operator precedence group they should belong to like this: `infix operator +-: AdditionPreference`.

## Closing Thoughts

If you made it here by reading through the entire post,
  🌟Congratulations!🌟
If you jumped around and just read the sections that interested you, that's fine too.  Thanks for reading, and please let me know in the comments if there are any mistakes, things I missed, and ways I can improve.