SlideShare a Scribd company logo
Advanced Swift Updated For Swift 5 Chris Eidhof
download
https://ebookbell.com/product/advanced-swift-updated-for-
swift-5-chris-eidhof-10575060
Explore and download more ebooks at ebookbell.com
Here are some recommended products that we believe you will be
interested in. You can click the link to download.
Advanced Swift Chris Eidhof Ole Begemann Florian Kugler Ben Cohen
https://ebookbell.com/product/advanced-swift-chris-eidhof-ole-
begemann-florian-kugler-ben-cohen-44569554
Advanced Swift 50 Chris Eidhof Ole Begemann Florian Kugler Ben Cohen
https://ebookbell.com/product/advanced-swift-50-chris-eidhof-ole-
begemann-florian-kugler-ben-cohen-44615496
Advanced Swift Objcio 3rd Edition Chris Eidhof Ole Begemann
https://ebookbell.com/product/advanced-swift-objcio-3rd-edition-chris-
eidhof-ole-begemann-7371436
Advanced Swift Chris Eidhofole Begemannairspeed Velocity
https://ebookbell.com/product/advanced-swift-chris-eidhofole-
begemannairspeed-velocity-11700822
Advanced Ios App Architecture Realworld App Architecture In Swift 2nd
Edition Ren Cacheaux
https://ebookbell.com/product/advanced-ios-app-architecture-realworld-
app-architecture-in-swift-2nd-edition-ren-cacheaux-38535306
Advanced Ios App Architecture Realworld App Architecture In Swift
Raywenderlich Tutorial Team
https://ebookbell.com/product/advanced-ios-app-architecture-realworld-
app-architecture-in-swift-raywenderlich-tutorial-team-11201840
Mastering Swift 2 Dive Into The Latest Release Of The Swift
Programming Language With This Advanced Apple Development Book For
Creating Exceptional Ios And Osx Applications Jon Hoffman
https://ebookbell.com/product/mastering-swift-2-dive-into-the-latest-
release-of-the-swift-programming-language-with-this-advanced-apple-
development-book-for-creating-exceptional-ios-and-osx-applications-
jon-hoffman-5470890
Subsecond Annealing Of Advanced Materials Annealing By Lasers Flash
Lamps And Swift Heavy Ions 1st Edition Matthias Voelskow
https://ebookbell.com/product/subsecond-annealing-of-advanced-
materials-annealing-by-lasers-flash-lamps-and-swift-heavy-ions-1st-
edition-matthias-voelskow-4601894
Culture Shift In Advanced Industrial Society Ronald Inglehart
https://ebookbell.com/product/culture-shift-in-advanced-industrial-
society-ronald-inglehart-51954864
Advanced Swift Updated For Swift 5 Chris Eidhof
Advanced Swift Updated For Swift 5 Chris Eidhof
Version 4.0 (May 2019)
© 2019 Kugler und Eidhof GbR
All Rights Reserved
For more books, articles, and videos visit us at https://www.objc.io.
Email: mail@objc.io
Twitter: @objcio
1 Introduction 10
Who Is This Book For? 12
Themes 13
Terminology 16
Swift Style Guide 20
Revision History 22
2 Built-In Collections 24
Arrays 25
Arrays and Mutability 25
Array Indexing 27
Transforming Arrays 29
Array Slices 41
Dictionaries 43
Mutating Dictionaries 44
Some Useful Dictionary Methods 44
Hashable Requirement 46
Sets 47
Set Algebra 48
Index Sets and Character Sets 49
Using Sets Inside Closures 50
Ranges 51
Countable Ranges 52
Partial Ranges 53
Range Expressions 53
Recap 54
3 Optionals 56
Sentinel Values 57
Replacing Sentinel Values with Enums 59
A Tour of Optional Techniques 61
if let 61
while let 62
Doubly Nested Optionals 64
if var and while var 65
Scoping of Unwrapped Optionals 66
Optional Chaining 70
The nil-Coalescing Operator 73
Using Optionals with String Interpolation 75
Optional map 77
Optional atMap 79
Filtering Out nils with compactMap 80
Equating Optionals 81
Comparing Optionals 84
When to Force-Unwrap 84
Improving Force-Unwrap Error Messages 86
Asserting in Debug Builds 87
Implicitly Unwrapped Optionals 89
Implicit Optional Behavior 90
Recap 90
4 Functions 91
Overview 92
Flexibility through Functions 99
Functions as Data 103
Functions as Delegates 110
Delegates, Cocoa Style 110
Delegates That Work with Structs 111
Functions Instead of Delegates 113
inout Parameters and Mutating Methods 116
Nested Functions and inout 119
When & Doesn’t Mean inout 119
Properties 120
Change Observers 121
Lazy Stored Properties 123
Subscripts 125
Custom Subscripts 126
Advanced Subscripts 126
Key Paths 128
Key Paths Can Be Modeled with Functions 130
Writable Key Paths 131
The Key Path Hierarchy 134
Key Paths Compared to Objective-C 135
Future Directions 135
Autoclosures 135
The @escaping Annotation 138
withoutActuallyEscaping 140
Recap 141
5 Structs and Classes 142
Value Types and Reference Types 143
Mutation 147
Mutating Methods 151
inout Parameters 152
Lifecycle 153
Reference Cycles 153
Closures and Reference Cycles 158
Choosing between Unowned and Weak References 160
Deciding between Structs and Classes 161
Classes with Value Semantics 162
Structs with Reference Semantics 163
Copy-On-Write Optimization 165
Copy-On-Write Tradeoffs 166
Implementing Copy-On-Write 167
Recap 171
6 Enums 173
Overview 174
Enums Are Value Types 175
Sum Types and Product Types 177
Pattern Matching 179
Pattern Matching in Other Contexts 183
Designing with Enums 185
Switch Exhaustively 186
Make Illegal States Impossible 187
Use Enums for Modeling State 191
Choosing between Enums and Structs 195
Parallels between Enums and Protocols 197
Use Enums to Model Recursive Data Structures 200
Raw Values 206
The RawRepresentable Protocol 207
Manual RawRepresentable Conformance 208
RawRepresentable for Structs and Classes 209
Internal Representation of Raw Values 210
Enumerating Enum Cases 211
Manual CaseIterable Conformance 212
Frozen and Non-Frozen Enums 213
Tips and Tricks 215
Recap 220
7 Strings 221
Unicode 222
Grapheme Clusters and Canonical Equivalence 224
Combining Marks 224
Emoji 227
Strings and Collections 230
Bidirectional, Not Random Access 231
Range-Replaceable, Not Mutable 232
String Indices 233
Substrings 237
StringProtocol 239
Code Unit Views 242
Index Sharing 244
Strings and Foundation 245
Other String-Related Foundation APIs 247
Ranges of Characters 249
CharacterSet 250
Unicode Properties 251
Internal Structure of String and Character 252
String Literals 254
String Interpolation 255
Custom String Descriptions 258
Text Output Streams 259
Recap 263
8 Generics 265
Generic Types 266
Extending Generic Types 268
Generics vs. Any 270
Designing with Generics 272
Recap 275
9 Protocols 276
Protocol Witnesses 278
Conditional Conformance 280
Protocol Inheritance 281
Designing with Protocols 282
Protocol Extensions 283
Customizing Protocol Extensions 284
Protocol Composition 287
Protocol Inheritance 288
Protocols with Associated Types 288
Conditional Conformance with Associated Types 290
Existentials 292
Existentials and Associated Types 293
Type Erasers 294
Retroactive Conformance 296
Recap 297
10 Collection Protocols 298
Sequences 300
Iterators 301
Conforming to Sequence 304
Iterators and Value Semantics 305
Function-Based Iterators and Sequences 307
Single-Pass Sequences 308
The Relationship between Sequences and Iterators 310
Conforming List to Sequence 311
Collections 313
A Custom Collection 314
Array Literals 320
Associated Types 321
Indices 322
Index Invalidation 324
Advancing Indices 325
Custom Collection Indices 326
Subsequences 329
Slices 331
Subsequences Share Indices with the Base Collection 333
Specialized Collections 334
BidirectionalCollection 335
RandomAccessCollection 336
MutableCollection 337
RangeReplaceableCollection 339
Lazy Sequences 341
Lazy Processing of Collections 343
Recap 344
11 Error Handling 345
Error Categories 346
The Result Type 348
Throwing and Catching 350
Typed and Untyped Errors 352
Non-Ignorable Errors 354
Error Conversions 356
Converting between throws and Optionals 356
Converting between throws and Result 357
Chaining Errors 358
Chaining throws 359
Chaining Result 359
Errors in Asynchronous Code 361
Cleaning Up Using defer 364
Rethrowing 365
Bridging Errors to Objective-C 367
Recap 369
12 Encoding and Decoding 371
A Minimal Example 373
Automatic Conformance 373
Encoding 374
Decoding 376
The Encoding Process 376
Containers 377
How a Value Encodes Itself 380
The Synthesized Code 380
Coding Keys 380
The encode(to:) Method 381
The init(from:) Initializer 382
Manual Conformance 382
Custom Coding Keys 383
Custom encode(to:) and init(from:) Implementations 384
Common Coding Tasks 386
Making Types You Don’t Own Codable 387
Making Classes Codable 390
Making Enums Codable 396
Decoding Polymorphic Collections 398
Recap 399
13 Interoperability 401
Wrapping a C Library 402
Package Manager Setup 402
Wrapping the CommonMark Library 405
A Safer Interface 411
An Overview of Low-Level Types 418
Pointers 419
Closures as C Callbacks 422
Making It Generic 424
Recap 427
14 Final Words 429
Introduction
1
Advanced Swift is quite a bold title for a book, so perhaps we should start with what we
mean by it.
When we began writing the first edition of this book, Swift was barely a year old. We did
so before the beta of 2.0 was released — albeit tentatively, because we suspected the
language would continue to evolve as it entered its second year. Few languages —
perhaps no other language — have been adopted so rapidly by so many developers.
But that left people with unanswered questions. How do you write “idiomatic” Swift? Is
there a correct way to do certain things? The standard library provided some clues, but
even that has changed over time, dropping some conventions and adopting others.
Since its introduction nearly five years ago, Swift has evolved at a high pace, and it has
become clearer what idiomatic Swift is.
To someone coming from another language, Swift can resemble everything they like
about their language of choice. Low-level bit twiddling can look very similar to (and can
be as performant as) C, but without many of the undefined behavior gotchas. The
lightweight trailing closure syntax of map or lter will be familiar to Rubyists. Swift
generics are similar to C++ templates, but with type constraints to ensure generic
functions are correct at the time of definition rather than at the time of use. The
flexibility of higher-order functions and operator overloading means you can write code
that’s similar in style to Haskell or F#. And the @objc and dynamic keywords allow you
to use selectors and runtime dynamism in ways you would in Objective-C.
Given these resemblances, it’s tempting to adopt the idioms of other languages. Case in
point: Objective-C example projects can be almost mechanically ported to Swift. The
same is true for Java or C# design patterns and most functional programming patterns.
But then comes the frustration. Why can’t we use protocol extensions with associated
types like interfaces in Java? Why are arrays not covariant in the way we expect? Why
can’t we write “functor?” Sometimes the answer is because the part of Swift in question
isn’t yet implemented. But more often, it’s either because there’s a different Swift-like
way to do what you want to do, or because the Swift feature you thought was like the
equivalent in some other language is, in reality, not quite what you think.
Swift is a complex language — most programming languages are. But it hides that
complexity well. You can get up and running developing apps in Swift without needing
to know about generics or overloading or the difference between static and dynamic
dispatch. You can certainly use Swift without ever calling into a C library or writing your
own collection type, but after a while, we think you’ll find it necessary to know about
these things — whether to improve your code’s performance, or to make it more elegant
or expressive, or just to get certain things done.
Learning more about these features is what this book is about. We intend to answer
many of the “How do I do this?” or “Why does Swift behave like that?” questions we’ve
seen come up again and again on various forums. Hopefully, once you’ve read our book,
you’ll have gone from being aware of the basics of the language to knowing about many
advanced features and having a much better understanding of how Swift works. Being
familiar with the material presented is probably necessary, if not sufficient, for calling
yourself an advanced Swift programmer.
Who Is This Book For?
This book targets experienced (though not necessarily expert) programmers, such as
existing Apple-platform developers. It’s also for those coming from other languages
such as Java or C++ who want to bring their knowledge of Swift to the same level as that
of their “go-to” language. Additionally, it’s suitable for new programmers who started on
Swift, have grown familiar with the basics, and are looking to take things to the next
level.
The book isn’t meant to be an introduction to Swift; it assumes you’re familiar with the
syntax and structure of the language. If you want some good, compact coverage of the
basics of Swift, the best source is the official Apple Swift book (available on iBooks or on
Apple’s website). If you’re already a confident programmer, you could try reading our
book and the Apple Swift book in parallel.
This is also not a book about programming for macOS or iOS devices. Of course, since
Swift is used a lot for development on Apple platforms, we’ve tried to include examples
of practical use, but we hope this book will be useful for non-Apple-platform
programmers as well. The vast majority of the examples in the book should run
unchanged on other operating systems. The ones that don’t are either fundamentally
tied to Apple’s platforms (because they use iOS frameworks or rely on the Objective-C
runtime) or only require minimal changes. We can say from personal experience that
Swift is a great language for writing server apps running on Linux, and the ecosystem
and community have evolved over the past few years to make this a viable option.
Themes
This book is organized in such a way that each chapter covers one specific concept.
There are in-depth chapters on some fundamental basic concepts like optionals and
strings, along with some deeper dives into topics like C interoperability. But throughout
the book, hopefully a few themes regarding Swift emerge:
Swift bridges multiple levels of abstraction. Swift is a high-level language — it allows
you to write code similarly to Ruby and Python, with map and reduce, and to write your
own higher-order functions easily. Swift also allows you to write fast code that compiles
directly to native binaries with performance similar to code written in C.
What’s exciting to us, and what’s possibly the aspect of Swift we most admire, is that
you’re able to do both these things at the same time. Mapping a closure expression over
an array compiles to the same assembly code as looping over a contiguous block of
memory does.
However, there are some things you need to know about to make the most of this feature.
For example, it will benefit you to have a strong grasp on how structs and classes differ,
or an understanding of the difference between dynamic and static method dispatch
(we’ll cover topics such as these in more depth later on). And if you ever need to drop to
a lower level of abstraction and manipulate pointers directly, Swift lets you to do this as
well.
Swift is a multi-paradigm language. You can use it to write object-oriented code or
pure functional code using immutable values, or you can write imperative C-like code
using pointer arithmetic.
This is both a blessing and a curse. It’s great in that you have a lot of tools available to
you, and you aren’t forced into writing code one way. But it also exposes you to the risk
of writing Java or C or Objective-C in Swift.
Swift still has access to most of the capabilities of Objective-C, including message
sending, runtime type identification, and key-value observation. But Swift introduces
many capabilities not available in Objective-C.
Erik Meijer, a well-known programming language expert, tweeted the following in
October 2015:
At this point, @SwiftLang is probably a better, and more valuable, vehicle for
learning functional programming than Haskell.
Swift is a good introduction to a more functional style of programming through its use of
generics, protocols, value types, and closures. It’s even possible to use it to write
operators that compose functions together. That said, most people in the Swift
community seem to prefer a more imperative style while incorporating patterns that
originated in functional programming. Swift’s notion of mutability for value types, as
well as its error handling model, are examples of the language “hiding” functional
concepts behind a friendly imperative syntax.
Swift is very flexible. In the introduction to the book On Lisp, Paul Graham writes that:
Experienced Lisp programmers divide up their programs differently. As well as
top-down design, they follow a principle which could be called bottom-up
design—changing the language to suit the problem. In Lisp, you don’t just
write your program down toward the language, you also build the language up
toward your program. As you’re writing a program you may think “I wish Lisp
had such-and-such an operator.” So you go and write it. Afterward you realize
that using the new operator would simplify the design of another part of the
program, and so on. Language and program evolve together.
Swift is very different from Lisp. But still, we feel like Swift also has this characteristic of
encouraging “bottom-up” programming — of making it easy to write very general
reusable building blocks that you then combine into larger features, which you then use
to solve your actual problem. Swift is particularly good at making these building blocks
feel like primitives — like part of the language. A good demonstration of this is that the
many features you might think of as fundamental building blocks, like optionals or basic
operators, are actually defined in a library — the Swift standard library — rather than
directly in the language. Trailing closures enable you to extend the language with
features that feel like they’re built in.
Swift code can be compact and concise while still being clear. Swift lends itself to
relatively terse code. There’s an underlying goal here, and it isn’t to save on typing. The
idea is to get to the point quicker and to make code readable by dropping a lot of the
“ceremonial” boilerplate you often see in other languages that obscures rather than
clarifies the meaning of the code.
For example, type inference removes the clutter of type declarations that are obvious
from the context. Semicolons and parentheses that add little or no value are gone.
Generics and protocol extensions encourage you to avoid repeating yourself by
packaging common operations into reusable functions. The goal is to write code that’s
readable at a glance.
At first, this can be off-putting. If you’ve never before used functions like map, lter, and
reduce, they might come across as more difficult to read than a simple for loop. But our
hope is that this is a short learning curve and that the reward is code that is more
“obviously correct” at first glance.
Swift tries to be as safe as is practical, until you tell it not to be. This is unlike
languages such as C and C++ (where you can be unsafe easily just by forgetting to do
something), or like Haskell or Java (which are sometimes safe whether or not you like it).
Eric Lippert, one of the principal designers of C#, wrote about his 10 regrets of C#,
including the lesson that:
sometimes you need to implement features that are only for experts who
are building infrastructure; those features should be clearly marked as
dangerous—not invitingly similar to features from other languages.
Eric was specifically referring to C#’s finalizers, which are similar to C++ destructors. But
unlike destructors, they run at a nondeterministic time (perhaps never) at the behest of
the garbage collector (and on the garbage collector’s thread). However, Swift, being
reference counted, does execute a class’s deinit deterministically.
Swift embodies this sentiment in other ways. Undefined and unsafe behavior is avoided
by default. For example, a variable can’t be used until it’s been initialized, and using
out-of-bounds subscripts on an array will trap, as opposed to continuing with possibly
garbage values.
There are a number of “unsafe” options available (such as the unsafeBitCast function, or
the UnsafeMutablePointer type) for when you really need them. But with great power
comes great undefined behavior. For example, you can write the following:
var someArray = [1, 2, 3]
let uhOh = someArray.withUnsafeBufferPointer { ptr in
return ptr
}
// Later...
print(uhOh[10])
It’ll compile, but who knows what it’ll do. The ptr variable is only valid within the
closure expression, and returning it to the caller is illegal. But there is nothing stopping
you from letting it escape into the wild. However, you can’t say nobody warned you.
Swift is an opinionated language. We as authors have strong opinions about the
“right” way to write Swift. You’ll see many of them in this book, sometimes expressed as
if they’re facts. But they’re just our opinions — feel free to disagree! Swift is still a young
language, and many things aren’t settled. Regardless of what you’re reading, the most
important thing is to try things out for yourself, check how they behave, and decide how
you feel about them. Think critically, and beware of out-of-date information.
Swift continues to evolve. The period of major yearly syntax changes is behind us, but
important areas of the language are still unfinished (string APIs, the generics system), in
flux (reflection), or haven’t been tackled yet (concurrency).
Terminology
‘When I use a word,’ Humpty Dumpty said, in rather a scornful tone, ‘it means
just what I choose it to mean — neither more nor less.’
— Through the Looking Glass, by Lewis Carroll
Programmers throw around terms of art a lot. To avoid confusion, what follows are some
definitions of terms we use throughout this book. Where possible, we’re trying to adhere
to the same usage as the official documentation, or sometimes a definition that’s been
widely adopted by the Swift community. Many of these definitions are covered in more
detail in later chapters, so don’t worry if not everything makes sense right away. If you’re
already familiar with all of these terms, it’s still best to skim through to make sure your
accepted meanings don’t differ from ours.
In Swift, we make the distinction between values, variables, references, and constants.
A value is immutable and forever — it never changes. For example, 1, true, and [1,2,3]
are all values. These are examples of literals, but values can also be generated at
runtime. The number you get when you square the number five is a value.
When we assign a value to a name using var x = [1,2], we’re creating a variable named x
that holds the value [1,2]. By changing x, e.g. by performing x.append(3), we didn’t
change the original value. Rather, we replaced the value that x holds with the new value,
[1,2,3] — at least logically, if not in the actual implementation (which might actually just
tack a new entry on the back of some existing memory). We refer to this as mutating the
variable.
We can declare constant variables (constants, for short) with let instead of var. Once a
constant has been assigned a value, it can never be assigned a new value.
We also don’t need to give a variable a value immediately. We can declare the variable
first (let x: Int) and then later assign a value to it (x = 1). Swift, with its emphasis on
safety, will check that all possible code paths lead to a variable being assigned a value
before its value can be read. There’s no concept of a variable having an as-yet-undefined
value. Of course, if the variable was declared with let, it can only be assigned to once.
Structs and enums are value types. When you assign one struct variable to another, the
two variables will then contain the same value. You can think of the contents as being
copied, but it’s more accurate to say that one variable was changed to contain the same
value as the other.
A reference is a special kind of value: it’s a value that “points to” some other location in
memory. Because two references can refer to the same location, this introduces the
possibility of the value stored at that location getting mutated by two different parts of
the program at once.
Classes are reference types. You can’t hold an instance of a class (which we might
occasionally call an object — a term fraught with troublesome overloading!) directly in
a variable. Instead, you must hold a reference to it in a variable and access it via that
reference.
Reference types have identity — you can check if two variables are referring to the exact
same object by using ===. You can also check if they’re equal, assuming == is
implemented for the relevant type. Two objects with different identities can still be
equal.
Value types don’t have identity. You can’t check if a particular variable holds the “same”
number 2 as another. You can only check if they both contain the value 2. === is really
asking: “Do both these variables hold the same reference as their value?” In
programming language literature, == is sometimes called structural equality, and ===
is called pointer equality or reference equality.
Class references aren’t the only kind of reference in Swift. For example, there are also
pointers, accessed through withUnsafeMutablePointer functions and the like. But
classes are the simplest reference type to use, in part because their reference-like nature
is partially hidden from you by syntactic sugar, meaning you don’t need to do any
explicit “dereferencing” like you do with pointers in some other languages. (We’ll cover
the other kind of references in more detail in the Interoperability chapter.)
A variable that holds a reference can be declared with let — that is, the reference is
constant. This means that the variable can never be changed to refer to something else.
But — and this is important — it doesn’t mean that the object it refers to can’t be changed.
So when referring to a variable as a constant, be careful — it’s only constant in what it
points to. It doesn’t mean what it points to is constant. (Note: If those last few sentences
sound like doublespeak, don’t worry, as we cover this again in the Structs and Classes
chapter.) Unfortunately, this means that when looking at a declaration of a variable with
let, you can’t tell at a glance whether or not what’s being declared is completely
immutable. Instead, you have to know whether it’s holding a value type or a reference
type.
When a value type is copied, it generally performs a deep copy, i.e. all values it contains
are also copied recursively. This copy can occur eagerly (whenever a new variable is
introduced) or lazily (whenever a variable gets mutated). Types that perform deep
copies are said to have value semantics.
Here we hit another complication. If a struct contains reference types, the referenced
objects won’t automatically get copied upon assigning the struct to a new variable.
Instead, only the references themselves get copied. These are called shallow copies.
For example, the Data struct in Foundation is a wrapper around a class that stores the
actual bytes. However, the authors of the Data struct took extra steps to also perform a
deep copy of the class instance whenever the Data struct is mutated. They do this
efficiently using a technique called copy-on-write, which we’ll explain in the Structs and
Classes chapter. For now, it’s important to know that this behavior doesn’t come for free.
The collections in the standard library also wrap reference types and use copy-on-write
to efficiently provide value semantics. However, if the elements in a collection are
references (for example, an array containing objects), the objects won’t get copied.
Instead, only the references get copied. This means that a Swift array only has value
semantics if its elements have value semantics too.
Some classes are completely immutable — that is, they provide no methods for changing
their internal state after they’re created. This means that even though they’re classes,
they also have value semantics (because even if they’re shared, they can never change).
Be careful though — only nal classes can be guaranteed not to be subclassed with
added mutable state.
In Swift, functions are also values. You can assign a function to a variable, have an array
of functions, and call the function held in a variable. Functions that take other functions
as arguments (such as map, which takes a function to transform every element of a
sequence) or return functions are referred to as higher-order functions.
Functions don’t have to be declared at the top level — you can declare a function within
another function or in a do or other scope. Functions defined within an outer scope but
passed out from it (say, as the returned value of a function), can “capture” local variables,
in which case those local variables aren’t destroyed when the local scope ends, and the
function can hold state through them. This behavior is called “closing over” variables,
and functions that do this are called closures.
Functions can be declared either with the func keyword or by using a shorthand { }
syntax called a closure expression. Sometimes this gets shortened to “closures,” but
don’t let it give you the impression that only closure expressions can be closures.
Functions declared with the func keyword are also closures when they close over
external variables.
Functions are held by reference. This means assigning a function that has captured state
to another variable doesn’t copy that state; it shares it, similar to object references.
What’s more is that when two closures close over the same local variable, they both share
that variable, so they share state. This can be quite surprising, and we’ll discuss this
more in the Functions chapter.
Functions defined inside a class or protocol are methods, and they have an implicit self
parameter. Sometimes we call functions that aren’t methods free functions. This is to
distinguish them from methods.
A fully qualified function name in Swift includes not just the function’s base name (the
part before the parentheses), but also the argument labels. For example, the full name of
the method for moving a collection index by a number of steps is index(_:offsetBy:),
indicating that this function takes two arguments (represented by the two colons), the
first one of which has no label (represented by the underscore). We often omit the labels
in the book if it’s clear from the context what function we’re referring to; the compiler
allows you to do the same.
Free functions, and methods called on structs, are statically dispatched. This means
the function that’ll be called is known at compile time. It also means the compiler might
be able to inline the function, i.e. not call the function at all, but instead replace it with
the code the function would execute. The optimizer can also discard or simplify code
that it can prove at compile time won’t actually run.
Methods on classes or protocols might be dynamically dispatched. This means the
compiler doesn’t necessarily know at compile time which function will run. This
dynamic behavior is done either by using vtables (similar to how Java and C++ dynamic
dispatch work), or in the case of some @objc classes and protocols, by using selectors
and objc_msgSend.
Subtyping and method overriding is one way of getting polymorphic behavior,
i.e. behavior that varies depending on the types involved. A second way is function
overloading, where a function is written multiple times for different types. (It’s
important not to mix up overriding and overloading, as they behave very differently.) A
third way is via generics, where a function or method is written once to take any type
that provides certain functions or methods, but the implementations of those functions
can vary. Unlike method overriding, the results of function overloading and generics are
known statically at compile time. We’ll cover this more in the Generics chapter.
Swift Style Guide
When writing this book, and when writing Swift code for our own projects, we try to stick
to the following rules:
→ For naming, clarity at the point of use is the most important consideration. Since
APIs are used many more times than they’re declared, their names should be
optimized for how well they work at the call site. Familiarize yourself with the
Swift API Design Guidelines and try to adhere to them in your own code.
→ Clarity is often helped by conciseness, but brevity should never be a goal in and of
itself.
→ Always add documentation comments to functions — especially generic ones.
→ Types start with UpperCaseLetters. Functions, variables, and enum cases start
with lowerCaseLetters.
→ Use type inference. Explicit but obvious types get in the way of readability.
→ Don’t use type inference in cases of ambiguity or when defining contracts (which
is why, for example, funcs have an explicit return type).
→ Default to structs unless you actually need a class-only feature or reference
semantics.
→ Mark classes as nal unless you’ve explicitly designed them to be inheritable. If
you want to use inheritance internally but not allow subclassing for external
clients, mark a class public but not open.
→ Use the trailing closure syntax, except when that closure is immediately followed
by another opening brace.
→ Use guard to exit functions early.
→ Eschew force-unwraps and implicitly unwrapped optionals. They’re occasionally
useful, but needing them constantly is usually a sign something is wrong.
→ Don’t repeat yourself. If you find you’ve written a very similar piece of code more
than a couple of times, extract it into a function. Consider making that function a
protocol extension.
→ Favor map and lter. But don’t force it: use a for loop when it makes sense. The
purpose of higher-order functions is to make code more readable. An obfuscated
use of reduce when a simple for loop would be clearer defeats this purpose.
→ Favor immutable variables: default to let unless you know you need mutation.
But use mutation when it makes the code clearer or more efficient. Again, don’t
force it: a mutating method on a struct is often more idiomatic and efficient than
returning a brand new struct.
→ Swift generics (especially in combination with protocol constraints) tend to lead
to very long function signatures. Unfortunately, we have yet to settle on a good
way of breaking up long function declarations into multiple lines. We’ll try to be
consistent in how we do this in sample code.
→ Leave off self. when you don’t need it. In closure expressions, the presence of
self. is a clear signal that self is being captured by the closure.
→ Instead of writing a free function, write an extension on a type or protocol
(whenever you can). This helps with readability and discoverability.
One final note about our code samples throughout the book: to save space and focus on
the essentials, we usually omit import statements that would be required to make the
code compile. If you try out the code yourself and the compiler tells you it doesn’t
recognize a particular symbol, try adding an import Foundation or import UIKit
statement.
Revision History
Fourth Edition (May 2019)
→ All chapters revised for Swift 5.
→ New chapter: Enums
→ Rewritten chapters:
→ Structs and Classes
→ Generics
→ Protocols
→ Significant changes and new content:
→ Strings
→ Collection Protocols
→ Error Handling
→ Reordered the chapters; Collection Protocols has been moved further back in the
book, resulting in a smoother learning curve for readers.
→ Florian Kugler joined as a co-author.
Third Edition (October 2017)
→ All chapters revised for Swift 4.
→ New chapter: Encoding and Decoding
→ Significant changes and new content:
→ Built-In Collections
→ Collection Protocols
→ Functions (new section on key paths)
→ Strings (more than 40 percent longer)
→ Interoperability
→ Full text available as Xcode playgrounds.
Second Edition (September 2016)
→ All chapters revised for Swift 3.
→ Split the Collections chapter into Built-In Collections and Collection Protocols.
→ Significant changes and new content throughout the book, especially in:
→ Collection Protocols
→ Functions
→ Generics
→ Full text available as a Swift playground for iPad.
→ Ole Begemann joined as a co-author.
First Edition (March 2016)
→ Initial release (covering Swift 2.2).
Built-In
Collections
2
Collections of elements are among the most important data types in any programming
language. Good language support for different kinds of containers has a big impact on
programmer productivity and happiness. Swift places special emphasis on sequences
and collections — so much of the standard library is dedicated to this topic that we
sometimes have the feeling it deals with little else. The resulting model is more
extensible than what you may be used to from other languages, but it’s also quite
complex.
In this chapter, we’re going to take a look at the major collection types Swift ships with,
with a focus on how to work with them effectively and idiomatically. In the Collection
Protocols chapter later in the book, we’ll climb up the abstraction ladder and see how
the collection protocols in the standard library work.
Arrays
Arrays and Mutability
Arrays are the most common collections in Swift. An array is an ordered container of
elements that all have the same type, and it provides random access to each element. As
an example, to create an array of numbers, we can write the following:
// The Fibonacci numbers
let fibs = [0, 1, 1, 2, 3, 5]
If we try to modify the array defined above (by using append(_:), for example), we get a
compile error. This is because the array is defined as a constant, using let. In many cases,
this is exactly the correct thing to do; it prevents us from accidentally changing the array.
If we want the array to be a variable, we have to define it using var:
var mutableFibs = [0, 1, 1, 2, 3, 5]
Now we can easily append a single element or a sequence of elements:
mutableFibs.append(8)
mutableFibs.append(contentsOf: [13, 21])
mutableFibs // [0, 1, 1, 2, 3, 5, 8, 13, 21]
There are a couple of benefits that come with making the distinction between var and let.
Constants defined with let are easier to reason about because they’re immutable. When
you read a declaration like let bs = ..., you know that the value of bs will never change
— the immutability is enforced by the compiler. This helps greatly when reading
through code. However, note that this is only true for types that have value semantics. A
let variable containing a reference to a class instance guarantees that the reference will
never change, i.e. you can’t assign another object to that variable. However, the object
the reference points to can change. We’ll go into more detail on these differences in the
chapter on Structs and Classes.
Arrays, like all collection types in the standard library, have value semantics. When you
assign an existing array to another variable, the array contents are copied over. For
example, in the following code snippet, x is never modified:
var x = [1,2,3]
var y = x
y.append(4)
y // [1, 2, 3, 4]
x // [1, 2, 3]
The statement var y = x makes a copy of x, so appending 4 to y won’t change x — the
value of x will still be [1, 2, 3]. The same thing happens when you pass an array into a
function; the function receives a local copy of the array, and any changes it makes don’t
affect the caller.
Compare this with the approach to mutability taken by NSArray in Foundation. NSArray
has no mutating methods — to mutate an array, you need an NSMutableArray. But just
because you have a non-mutating NSArray reference does not mean the array can’t be
mutated underneath you:
let a = NSMutableArray(array: [1,2,3])
// I don't want to be able to mutate b.
let b: NSArray = a
// But it can still be mutated — via a.
a.insert(4, at: 3)
b // ( 1, 2, 3, 4 )
The correct way to write this is to manually create a copy upon assignment:
let c = NSMutableArray(array: [1,2,3])
// I don't want to be able to mutate d.
let d = c.copy() as! NSArray
c.insert(4, at: 3)
d // ( 1, 2, 3 )
In the example above, it’s very clear that we need to make a copy — a is mutable, after all.
However, when passing around arrays between methods and functions, this isn’t always
so easy to see.
In Swift, there’s just one array type, and mutability is controlled by declaring with var
instead of let. But there’s no reference sharing — when you declare a second array with
let, you’re guaranteed it’ll never change.
Making so many copies could be a performance problem, but in practice, all collection
types in the Swift standard library are implemented using a technique called
copy-on-write, which makes sure the data is only copied when necessary. So in our
example, x and y shared internal storage up until the point y.append was called. In the
chapter on Structs and Classes, we’ll take a deeper look at value semantics, including
how to implement copy-on-write for your own types:
Array Indexing
Swift arrays provide all the usual operations you’d expect, such as isEmpty and count.
Arrays also allow for direct access of elements at a specific index through subscripting,
like with bs[3]. Keep in mind that you need to make sure the index is within bounds
before getting an element via subscript. Fetch the element at index 3, and you’d better
be sure the array has at least four elements in it. Otherwise, your program will trap,
i.e. abort with a fatal error.
Swift has many ways to work with arrays without you ever needing to calculate an index:
→ Want to iterate over the array?
for x in array
→ Want to iterate over all but the first element of an array?
for x in array.dropFirst()
→ Want to iterate over all but the last five elements?
for x in array.dropLast(5)
→ Want to number all the elements in an array?
for (num, element) in array.enumerated()
→ Want to find the location of a specific element?
if let idx = array. rstIndex { someMatchingLogic($0) }
→ Want to transform all the elements in an array?
array.map { someTransformation($0) }
→ Want to fetch only the elements matching a specific criterion?
array. lter { someCriteria($0) }
Another sign that Swift wants to discourage you from doing index math is the removal of
traditional C-style for loops from the language in Swift 3. Manually fiddling with indices
is a rich sea of bugs to mine, so it’s often best avoided.
But sometimes you do have to use an index. And with array indices, the expectation is
that when you do, you’ll have thought very carefully about the logic behind the index
calculation. So to have to unwrap the value of a subscript operation is probably overkill
— it means you don’t trust your code. But chances are you do trust your code, so you’ll
probably resort to force-unwrapping the result, because you know the index must be
valid. This is (a) annoying, and (b) a bad habit to get into. When force-unwrapping
becomes routine, eventually you’re going to slip up and force-unwrap something you
don’t mean to. So to avoid this habit becoming routine, arrays don’t give you the option.
While a subscripting operation that responds to an invalid index with a
controlled crash could arguably be called unsafe, that’s only one aspect of
safety. Subscripting is totally safe in regard to memory safety — the standard
library collections always perform bounds checks to prevent unauthorized
memory access with an out-of-bounds index.
Other operations behave differently. The rst and last properties return an optional
value, which is nil if the array is empty. rst is equivalent to isEmpty ? nil : self[0].
Similarly, the removeLast method will trap if you call it on an empty array, whereas
popLast will only delete and return the last element if the array isn’t empty, and
otherwise it will do nothing and return nil. Which one you’d want to use depends on
your use case. When you’re using the array as a stack, you’ll probably always want to
combine checking for empty and removing the last entry. On the other hand, if you
already know whether or not the array is empty, dealing with the optional is fiddly.
We’ll encounter these tradeoffs again later in this chapter when we talk about
dictionaries. Additionally, there’s an entire chapter dedicated to Optionals.
Transforming Arrays
map
It’s common to need to perform a transformation on every value in an array. Every
programmer has written similar code hundreds of times: create a new array, loop over all
the elements in an existing array, perform an operation on an element, and append the
result of that operation to the new array. For example, the following code squares an
array of integers:
var squared: [Int] = []
for fib in fibs {
squared.append(fib * fib)
}
squared // [0, 1, 1, 4, 9, 25]
Swift arrays have a map method, which was adopted from the world of functional
programming. Here’s the exact same operation using map:
let squares = fibs.map { fib in fib * fib }
squares // [0, 1, 1, 4, 9, 25]
This version has three main advantages. It’s shorter, of course. There’s also less room for
error. But more importantly, it’s clearer: all the clutter has been removed. Once you’re
used to seeing and using map everywhere, it acts as a signal — you see map, and you
immediately know what’s happening: a function is going to be applied to every element,
returning a new array of the transformed elements.
The declaration of squared no longer needs to be made with var, because we aren’t
mutating it any longer — it’ll be delivered out of the map fully formed, so we can declare
squares with let, if appropriate. And because the type of the contents can be inferred
from the function passed to map, squares no longer needs to be explicitly typed.
The map method isn’t hard to write — it’s just a question of wrapping up the boilerplate
parts of the for loop into a generic function. Here’s one possible implementation
(though in Swift, it’s actually an extension of the Sequence protocol, which we’ll cover in
the Collection Protocols chapter):
extension Array {
func map<T>(_ transform: (Element) -> T) -> [T] {
var result: [T] = []
result.reserveCapacity(count)
for x in self {
result.append(transform(x))
}
return result
}
}
Element is the generic placeholder for whatever type the array contains, and T is a new
placeholder that represents the result of the element transformation. The map function
itself doesn’t care what Element and T are; they can be anything at all. The concrete type
T of the transformed elements is defined by the return type of the transform function the
caller passes to map. See the Generics chapter for details on generic parameters.
Really, the signature of this method should be
func map<T>(_ transform: (Element) throws -> T) rethrows -> [T], indicating that
map will forward any error the transformation function might throw to the
caller. We’ll cover this in detail in the Errors chapter, but here we’ve left the
error handling annotations out for the sake of simplicity. If you’d like, you can
check out the source code for Sequence.map in the Swift repository on GitHub.
Parameterizing Behavior with Functions
Even if you’re already familiar with map, take a moment and consider the map
implementation. What makes it so general yet so useful?
map manages to separate out the boilerplate — which doesn’t vary from call to call —
from the functionality that always varies, i.e. the logic of how exactly to transform each
element. It does this through a parameter the caller supplies: the transformation
function.
This pattern of parameterizing behavior is found throughout the standard library. For
example, there are more than a dozen separate methods on Array (and on other kinds of
collections) that take a function to customize their behavior:
→ map and atMap — transform the elements
→ lter — include only certain elements
→ allSatisfy — test all elements for a condition
→ reduce — fold the elements into an aggregate value
→ forEach — visit each element
→ sort(by:), sorted(by:), lexicographicallyPrecedes(_:by:), and partition(by:) —
reorder the elements
→ rstIndex(where:), lastIndex(where:), rst(where:), last(where:), and
contains(where:) — does an element exist?
→ min(by:) and max(by:) — find the minimum or maximum of all elements
→ elementsEqual(_:by:) and starts(with:by:) — compare the elements to another
array
→ split(whereSeparator:) — break up the elements into multiple arrays
→ pre x(while:) — take elements from the start as long as the condition holds true
→ drop(while:) — drop elements until the condition ceases to be true, and then
return the rest (similar to pre x, but this returns the inverse)
→ removeAll(where:) — remove the elements matching the condition
The goal of all these functions is to get rid of the clutter of the uninteresting parts of the
code, such as the creation of a new array and the for loop over the source data. Instead,
the clutter is replaced with a single word that describes what’s being done. This brings
the important code – the logic the programmer wants to express – to the forefront.
Several of these functions have a default behavior. sort sorts elements in ascending
order when they’re comparable, unless you specify otherwise, and contains can take a
value to check for, so long as the elements are equatable. These defaults help make the
code even more readable. Ascending order sorting is natural, so the meaning of
array.sort() is intuitive, and array. rstIndex(of: "foo") is clearer than
array. rstIndex { $0 == "foo" }.
But in every instance, these are just shorthand for the common cases. Elements don’t
have to be comparable or equatable, and you don’t have to compare the entire element —
you can sort an array of people by their ages (people.sort { $0.age < $1.age }) or check if
the array contains anyone underage (people.contains { $0.age < 18 }). You can also
compare some transformation of the element. For example, an admittedly inefficient
case- and locale-insensitive sort could be performed via
people.sort { $0.name.uppercased() < $1.name.uppercased() }.
There are other functions of similar usefulness that would also take a function to specify
their behaviors but which aren’t in the standard library. You could easily define them
yourself (and might like to try):
→ accumulate — combine elements into an array of running values (like reduce, but
returning an array of each interim combination)
→ count(where:) — count the number of elements that match (this should have
been part of the Swift 5.0 standard library, but got delayed due to a name clash
with the count property; it will probably be reintroduced in a subsequent release
though)
→ indices(where:) — return a list of indices matching a condition (similar to
rstIndex(where:), but it doesn’t stop on the first one)
If you find yourself iterating over an array to perform the same task or a similar one
more than a couple of times in your code, consider writing a short extension to Array.
For example, the following code splits an array into groups of adjacent equal elements:
let array: [Int] = [1, 2, 2, 2, 3, 4, 4]
var result: [[Int]] = array.isEmpty ? [] : [[array[0]]]
for (previous, current) in zip(array, array.dropFirst()) {
if previous == current {
result[result.endIndex-1].append(current)
} else {
result.append([current])
}
}
result // [[1], [2, 2, 2], [3], [4, 4]]
We can formalize this algorithm by abstracting the code that loops over the array in pairs
of adjacent elements from the logic that varies between applications (deciding where to
split the array). We use a function argument to allow the caller to customize the latter:
extension Array {
func split(where condition: (Element, Element) -> Bool) -> [[Element]] {
var result: [[Element]] = array.isEmpty ? [] : [[self[0]]]
for (previous, current) in zip(self, self.dropFirst()) {
if condition(previous, current) {
result.append([current])
} else {
result[result.endIndex-1].append(current)
}
}
return result
}
}
This allows us to replace the for loop with the following:
let parts = array.split { $0 != $1 }
parts // [[1], [2, 2, 2], [3], [4, 4]]
Or, in the case of this particular condition, we can even write:
let parts2 = array.split(where: !=)
This has all the same benefits we described for map. The example with split(where:) is
more readable than the example with the for loop; even though the for loop is simple,
you still have to run the loop through in your head, which is a small mental tax. Using
split(where:) introduces less chance of error (for example, accidentally forgetting the
case of the array being empty), and it allows you to declare the result variable with let
instead of var.
We’ll say more about extending collections and using functions later in the book.
Mutation and Stateful Closures
When iterating over an array, you could use map to perform side effects (e.g. inserting
elements into some lookup table). We don’t recommend doing this. Take a look at the
following:
array.map { item in
table.insert(item)
}
This hides the side effect (the mutation of the lookup table) in a construct that looks like
a transformation of the array. If you ever see something like the above, then it’s a clear
case for using a plain for loop instead of a function like map. The forEach method would
also be more appropriate than map in this case, but it has its own issues, so we’ll look at
forEach a bit later.
Performing side effects is different than deliberately giving the closure local state, which
is a particularly useful technique. In addition to being useful, it’s what makes closures —
functions that can capture and mutate variables outside their scope — so powerful a tool
when combined with higher-order functions. For example, the accumulate function
described above could be implemented with map and a stateful closure, like this:
extension Array {
func accumulate<Result>(_ initialResult: Result,
_ nextPartialResult: (Result, Element) -> Result) -> [Result]
{
var running = initialResult
return map { next in
running = nextPartialResult(running, next)
return running
}
}
}
This creates a temporary variable to store the running value and then uses map to create
an array of the running values as the computation progresses:
[1,2,3,4].accumulate(0, +) // [1, 3, 6, 10]
Note that this code assumes that map performs its transformation in order over the
sequence. In the case of our map above, it does. But there are possible implementations
that could transform the sequence out of order — for example, one that performs the
transformation of the elements concurrently. The official standard library version of
map doesn’t specify whether or not it transforms the sequence in order, though it seems
like a safe bet that it does.
lter
Another very common operation is that of taking an array and creating a new array that
only includes the elements that match a certain condition. The pattern of looping over
an array and selecting the elements that match the given predicate is captured in the
lter method:
let nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
nums.filter { num in num % 2 == 0 } // [2, 4, 6, 8, 10]
We can use Swift’s shorthand notation for arguments of a closure expression to make
this even shorter. Instead of naming the num argument, we can write the above code like
this:
nums.filter { $0 % 2 == 0 } // [2, 4, 6, 8, 10]
For very short closures, this can be more readable. If the closure is more complicated,
it’s almost always a better idea to name the arguments explicitly, as we’ve done before.
It’s really a matter of personal taste — choose whichever option is more readable at a
glance. A good rule of thumb is this: if the closure fits neatly on one line, shorthand
argument names are a good fit.
By combining map and lter, we can write a lot of operations on arrays without having to
introduce a single intermediate variable. The resulting code will become shorter and
easier to read. For example, to find all squares under 100 that are even, we could map
the range 1..<10 in order to square its members, and then we could filter out all odd
numbers:
(1..<10).map { $0 * $0 }.filter { $0 % 2 == 0 } // [4, 16, 36, 64]
The implementation of lter looks similar to map:
extension Array {
func filter(_ isIncluded: (Element) -> Bool) -> [Element] {
var result: [Element] = []
for x in self where isIncluded(x) {
result.append(x)
}
return result
}
}
One quick performance tip: if you ever find yourself writing something like the
following, stop!
bigArray.filter { someCondition }.count > 0
lter creates a brand-new array and processes every element in the array. But this is
unnecessary. This code only needs to check if one element matches — in which case,
contains(where:) will do the job:
bigArray.contains { someCondition }
This is much faster for two reasons: it doesn’t create a whole new array of the filtered
elements just to count them, and it exits early — as soon as it finds the first match.
Generally, only ever use lter if you want all the results.
reduce
Both map and lter take an array and produce a new, modified array. Sometimes,
however, you might want to combine all elements into a single new value. For example,
to sum up all the elements, we could write the following code:
let fibs = [0, 1, 1, 2, 3, 5]
var total = 0
for num in fibs {
total = total + num
}
total // 12
The reduce method takes this pattern and abstracts two parts: the initial value (in this
case, zero), and the function for combining the intermediate value (total) and the
element (num). Using reduce, we can write the same example like this:
let sum = fibs.reduce(0) { total, num in total + num } // 12
Operators are functions too, so we could’ve also written the same example like this:
fibs.reduce(0, +) // 12
The output type of reduce doesn’t have to be the same as the element type. For example,
if we want to convert a list of integers into a string, with each number followed by a
comma and a space, we can do the following:
fibs.reduce("") { str, num in str + "(num), " } // 0, 1, 1, 2, 3, 5,
Here’s the implementation for reduce:
extension Array {
func reduce<Result>(_ initialResult: Result,
_ nextPartialResult: (Result, Element) -> Result) -> Result
{
var result = initialResult
for x in self {
result = nextPartialResult(result, x)
}
return result
}
}
Another performance tip: reduce is very flexible, and it’s common to see it used to build
arrays and perform other operations. For example, you can implement map and lter
using only reduce:
extension Array {
func map2<T>(_ transform: (Element) -> T) -> [T] {
return reduce([]) {
$0 + [transform($1)]
}
}
func filter2(_ isIncluded: (Element) -> Bool) -> [Element] {
return reduce([]) {
isIncluded($1) ? $0 + [$1] : $0
}
}
}
This is kind of beautiful and has the benefit of not needing those icky imperative for
loops. But Swift isn’t Haskell, and Swift arrays aren’t lists. What’s happening here is that
on every execution of the combine function, a brand-new array is being created by
appending the transformed or included element to the previous one. This means that
both these implementations are O(n2), not O(n) — as the length of the array increases,
the time these functions take increases quadratically.
There’s a second version of reduce, which has a different type. More specifically, the
function for combining an intermediate result and an element takes Result as an inout
parameter:
public func reduce<Result>(into initialResult: Result,
_ updateAccumulatingResult:
(_ partialResult: inout Result, Element) throws -> ()
) rethrows -> Result
We discuss inout parameters in detail in the chapter on Structs and Classes, but for now,
think of the inout Result parameter as a mutable parameter: we can modify it within the
function. This allows us to write lter in a much more efficient way:
extension Array {
func filter3(_ isIncluded: (Element) -> Bool) -> [Element] {
return reduce(into: []) { result, element in
if isIncluded(element) {
result.append(element)
}
}
}
}
When using inout, the compiler doesn’t have to create a new array each time, so this
version of lter is again O(n). When the call to reduce(into:_:) is inlined by the compiler,
the generated code is often the same as when using a for loop.
A Flattening map
Sometimes, you want to map an array where the transformation function returns
another array and not a single element.
For example, let’s say we have a function, extractLinks, that takes a Markdown file and
returns an array containing the URLs of all the links in the file. The function signature
looks like this:
func extractLinks(markdownFile: String) -> [URL]
If we have a bunch of Markdown files and want to extract the links from all files into a
single array, we could try to write something like markdownFiles.map(extractLinks). But
this returns an array of arrays containing the URLs: one array per file. Now you could
just perform the map, get back an array of arrays, and then call joined to flatten the
results into a single array:
let markdownFiles: [String] = // ...
let nestedLinks = markdownFiles.map(extractLinks)
let links = nestedLinks.joined()
The atMap method combines these two operations, mapping and flattening, into a
single step. So markdownFiles. atMap(extractLinks) returns all the URLs in an array of
Markdown files as a single array.
The signature for atMap is almost identical to map, except its transformation function
returns an array. The implementation uses append(contentsOf:) instead of append(_:) to
flatten the result array:
extension Array {
func flatMap<T>(_ transform: (Element) -> [T]) -> [T] {
var result: [T] = []
for x in self {
result.append(contentsOf: transform(x))
}
return result
}
}
Another great use case for atMap is combining elements from different arrays. To get
all possible pairs of the elements in two arrays, atMap over one array and then map
over the other in the inner transformation function:
let suits = ["♠", "♥", "♣", "♦"]
let ranks = ["J", "Q", "K", "A"]
let result = suits.flatMap { suit in
ranks.map { rank in
(suit, rank)
}
}
/*
[("♠", "J"), ("♠", "Q"), ("♠", "K"), ("♠", "A"), ("♥", "J"), ("♥",
"Q"), ("♥", "K"), ("♥", "A"), ("♣", "J"), ("♣", "Q"), ("♣", "K"),
("♣", "A"), ("♦", "J"), ("♦", "Q"), ("♦", "K"), ("♦", "A")]
*/
Iteration Using forEach
The final operation we’d like to discuss is forEach. It works almost like a for loop: the
passed-in function is executed once for each element in the sequence. And unlike map,
forEach doesn’t return anything — it is specifically meant for performing side effects.
Let’s start by mechanically replacing a loop with forEach:
for element in [1, 2, 3] {
print(element)
}
[1, 2, 3].forEach { element in
print(element)
}
This isn’t a big win, but it can be handy if the action you want to perform is a single
function call on each element in a collection. Passing a function name to forEach
instead of passing a closure expression can lead to clearer and more concise code. For
example, if you’re writing a view controller on iOS and want to add an array of subviews
to the main view, you can just use theViews.forEach(view.addSubview).
However, there are some subtle differences between for loops and forEach. For instance,
if a for loop has a return statement in it, rewriting it with forEach can significantly
change the code’s behavior. Consider the following example, which is written using a for
loop with a where condition:
extension Array where Element: Equatable {
func firstIndex(of element: Element) -> Int? {
for idx in self.indices where self[idx] == element {
return idx
}
return nil
}
}
We can’t directly replicate the where clause in the forEach construct, so we might
(incorrectly) rewrite this using lter:
extension Array where Element: Equatable {
func firstIndex_foreach(of element: Element) -> Int? {
self.indices.filter { idx in
self[idx] == element
}.forEach { idx in
return idx
}
return nil
}
}
The return inside the forEach closure doesn’t return out of the outer function; it only
returns from the closure itself. In this particular case, we’d probably have found the bug,
because the compiler generates a warning that the argument to the return statement is
unused, but you shouldn’t rely on it finding every such issue.
Also, consider the following example:
(1..<10).forEach { number in
print(number)
if number > 2 { return }
}
It’s not immediately obvious that this prints out all the numbers in the input range. The
return statement isn’t breaking the loop; rather, it’s returning from the closure, thus
starting a new iteration of the loop inside forEachs’s implementation.
In some situations, such as the addSubview example above, forEach can be nicer than a
for loop. However, because of the non-obvious behavior of return, we recommend
against most other uses of forEach. Just use a regular for loop instead.
Array Slices
In addition to accessing a single element of an array by subscript (e.g. bs[0]), we can
also retrieve a range of elements by subscript. For example, to get all but the first
element of an array, we can do the following:
let slice = fibs[1...]
slice // [1, 1, 2, 3, 5]
type(of: slice) // ArraySlice<Int>
This gets us a slice of the array starting at the second element. The type of the result is
ArraySlice, not Array. ArraySlice is a view on arrays. It’s backed by the original array, yet
it provides a view on just the slice. As a result, creating a slice is cheap — the array
elements don’t get copied.
length: Int 6
storage: Pointer ptr
0
storage: Pointer
startIndex: Int
ptr
1
endIndex: Int 6
1 1 2 3 Unused reserved capacity
Contents of !bs…
… shares the same storage as slice
5
Figure 2.1: Array Slices
The ArraySlice type has the same methods defined as Array does (because both conform
to the same protocols, most importantly Collection), so you can use a slice as if it were an
array. If you do need to convert a slice into an array, you can just construct a new array
out of the slice:
let newArray = Array(slice)
type(of: newArray) // Array<Int>
It’s important to keep in mind that slices use the same index as their base collection
does to refer to a particular element. As a consequence, slice indices don’t necessarily
start at zero. For example, the first element of the bs[1...] slice we created above is at
index 1, and accessing slice[0] by mistake would crash our program with an
out-of-bounds violation. If you work with indices, we recommend you always base your
calculations on the startIndex and endIndex properties, even if you’re dealing with a
plain array where 0 and count-1 would also do the trick. It’s just too easy for this implicit
assumption to break later on.
Dictionaries
Another key data structure is Dictionary. A dictionary contains unique keys with
corresponding values. Retrieving a value by its key takes constant time on average,
whereas searching an array for a particular element grows linearly with the array’s size.
Unlike arrays, dictionaries aren’t ordered; the order in which key-value pairs are
enumerated in a for loop is undefined.
In the following example, we use a dictionary as the model data for a fictional settings
screen in a smartphone app. The screen consists of a list of settings, and each individual
setting has a name (the keys in our dictionary) and a value. A value can be one of several
data types, such as text, numbers, or Booleans. We use an enum with associated values
to model this:
enum Setting {
case text(String)
case int(Int)
case bool(Bool)
}
let defaultSettings: [String:Setting] = [
"Airplane Mode": .bool(false),
"Name": .text("My iPhone"),
]
defaultSettings["Name"] // Optional(Setting.text("My iPhone"))
We use subscripting to get the value of a setting. Dictionary lookup always returns an
optional value — when the specified key doesn’t exist, it returns nil. Compare this with
arrays, which respond to an out-of-bounds access by crashing the program.
Dictionaries also have a subscript that takes an index (in contrast to the
commonly used subscript that takes a key) as part of their conformance to the
Collection protocol. This subscript traps when called with an invalid index, just
like the array subscript does.
The rationale for this difference is that array indices and dictionary keys are used very
differently. We’ve already seen that it’s quite rare that you actually need to work with
array indices directly. And if you do, an array index is usually directly derived from the
array in some way (e.g. from a range like 0..<array.count); thus, using an invalid index is
a programmer error. On the other hand, it’s very common for dictionary keys to come
from some source other than the dictionary being subscripted.
Unlike arrays, dictionaries are also sparse. The existence of the value under the key
"name" doesn’t tell you anything about whether or not the key “address” also exists.
Mutating Dictionaries
Just like arrays, dictionaries defined using let are immutable: no entries can be added,
removed, or changed. And just like with arrays, we can define a mutable variant using
var. To remove a value from a dictionary, we can either set it to nil using subscripting or
call removeValue(forKey:). The latter also returns either the deleted value, or nil if the key
didn’t exist. If we want to take an immutable dictionary and make changes to it, we have
to make a copy:
var userSettings = defaultSettings
userSettings["Name"] = .text("Jared's iPhone")
userSettings["Do Not Disturb"] = .bool(true)
Note that, again, the value of defaultSettings didn’t change. As with key removal, an
alternative to updating via subscript is the updateValue(_:forKey:) method, which
returns the previous value (if any):
let oldName = userSettings
.updateValue(.text("Jane's iPhone"), forKey: "Name")
userSettings["Name"] // Optional(Setting.text("Jane's iPhone"))
oldName // Optional(Setting.text("Jared's iPhone"))
Some Useful Dictionary Methods
What if we wanted to combine the default settings dictionary with any custom settings
the user has changed? Custom settings should override defaults, but the resulting
dictionary should still include default values for any keys that haven’t been customized.
Essentially, we want to merge two dictionaries, where the dictionary that’s being merged
in overwrites duplicate keys.
Dictionary has a merge(_:uniquingKeysWith:) method, which takes the key-value pairs to
be merged in and a function that specifies how to combine two values with the same key.
We can use this to merge one dictionary into another, as shown in the following
example:
var settings = defaultSettings
let overriddenSettings: [String:Setting] = ["Name": .text("Jane's iPhone")]
settings.merge(overriddenSettings, uniquingKeysWith: { $1 })
settings
// ["Name": Setting.text("Jane's iPhone"), "Airplane Mode": Setting.bool(false)]
In the example above, we used { $1 } as the policy for combining two values. In other
words, if a key exists in both settings and overriddenSettings, we use the value from
overriddenSettings.
We can also construct a new dictionary out of a sequence of (Key,Value) pairs. If we
guarantee that the keys are unique, we can use Dictionary(uniqueKeysWithValues:).
However, if we have a sequence where a key can exist multiple times, we need to provide
a function to combine two values for the same keys, just like above. For example, to
compute how often elements appear in a sequence, we can map over each element,
combine it with a 1, and then create a dictionary out of the resulting element-frequency
pairs. If we encounter two values for the same key (in other words, if we see the same
element more than once), we simply add the frequencies up using +:
extension Sequence where Element: Hashable {
var frequencies: [Element:Int] {
let frequencyPairs = self.map { ($0, 1) }
return Dictionary(frequencyPairs, uniquingKeysWith: +)
}
}
let frequencies = "hello".frequencies // ["h": 1, "e": 1, "l": 2, "o": 1]
frequencies.filter { $0.value > 1 } // ["l": 2]
Another useful method is a map over the dictionary’s values. Because Dictionary is a
Sequence, it already has a map method that produces an array. However, sometimes we
want to keep the dictionary structure intact and only transform its values. The
mapValues method does just this:
let settingsAsStrings = settings.mapValues { setting -> String in
switch setting {
case .text(let text): return text
case .int(let number): return String(number)
case .bool(let value): return String(value)
}
}
settingsAsStrings // ["Name": "Jane's iPhone", "Airplane Mode": "false"]
Hashable Requirement
Dictionaries are hash tables. A dictionary assigns each key a position in its underlying
storage array based on the key’s hashValue. This is why Dictionary requires its Key type
to conform to the Hashable protocol. All the basic data types in the standard library —
including strings, integers, floating-point numbers, and Boolean values — already do.
Additionally, many other types — like arrays, sets, and optionals — automatically
become hashable if their elements are hashable.
To maintain their performance guarantees, hash tables require the types stored in them
to provide a good hash function that doesn’t produce too many collisions. Writing a
good hash function that distributes its inputs uniformly over the full integer range isn’t
easy. Fortunately, we almost never have to do this ourselves. The compiler can generate
the Hashable conformance in many cases, and even if that doesn’t work for a particular
type, the standard library comes with a built-in hash function that custom types can
hook into.
For structs and enums, Swift can automatically synthesize the Hashable conformance
for us as long as they are themselves composed of hashable types. If all stored properties
of a struct are hashable, then the struct itself can be conformed to Hashable without us
having to write a manual implementation. Similarly, enums that only contain hashable
associated values can be conformed for free (enums without associated values even
conform to Hashable without declaring this conformance explicitly). Not only does this
save initial implementation work, but it also keeps the implementation up to date
automatically as properties get added or removed.
If you can’t take advantage of the automatic Hashable synthesis (because either you’re
writing a class or your custom struct has one or more stored properties that should be
ignored for hashing purposes), you first need to make the type Equatable. Then you can
implement the hash(into:) requirement of the Hashable protocol (the old pre-Swift 4.2
way of implementing the hashValue property is deprecated). This method receives a
Hasher, which wraps a universal hash function and captures the state of the hash
function as clients feed data into it. The hasher has a combine method that accepts any
hashable value. You should feed all essential components of your type to the hasher by
passing them to combine one by one. The essential components are the properties that
make up the substance of the type — you’ll usually want to exclude transient properties
that can be recreated lazily.
You should use the same essential components for equality checking, because the
following important invariant must hold: two instances that are equal (as defined by
your == implementation) must have the same hash value. The reverse isn’t true: two
instances with the same hash value don’t necessarily compare equally. This makes
sense, considering there’s only a finite number of distinct hash values, while many
hashable types (like strings) have essentially infinite cardinality.
The standard library’s universal hash function uses a random seed as one of its
inputs. In other words, the hash value of, say, the string "abc" will be different
on each program execution. Random seeding is a security measure to protect
against targeted hash-flooding denial of service attacks. Since Dictionary
and Set iterate over their elements in the order they are stored in the hash
table, and since this order is determined by the hash values, this means the
same code will produce different iteration orders on each launch. If you need
deterministic hashing (e.g. for tests), you can disable random seeding by
setting the environment variable SWIFT_DETERMINISTIC_HASHING=1, but you
shouldn’t do this in production.
Finally, be extra careful when you use types that don’t have value semantics
(e.g. mutable objects) as dictionary keys. If you mutate an object after using it as a
dictionary key in a way that changes its hash value and/or equality, you won’t be able to
find it again in the dictionary. The dictionary now stores the object in the wrong slot,
effectively corrupting its internal storage. This isn’t a problem with value types because
the key in the dictionary doesn’t share your copy’s storage and therefore can’t be
mutated from the outside.
Sets
The third major collection type in the standard library is Set. A set is an unordered
collection of elements, with each element appearing only once. You can essentially
think of a set as a dictionary that only stores keys and no values. Like Dictionary, Set is
implemented with a hash table and has similar performance characteristics and
requirements. Testing a value for membership in a set is a constant-time operation, and
set elements must be Hashable, just like dictionary keys.
Use a set instead of an array when you need to test efficiently for membership (an O(n)
operation for arrays) and the order of the elements is not important, or when you need to
ensure that a collection contains no duplicates.
Set conforms to the ExpressibleByArrayLiteral protocol, which means we can initialize it
with an array literal like this:
let naturals: Set = [1, 2, 3, 2]
naturals // [2, 3, 1]
naturals.contains(3) // true
naturals.contains(0) // false
Note that the number 2 appears only once in the set; the duplicate never even gets
inserted.
Like all collections, sets support the common operations we’ve already seen: you can
iterate over the elements in a for loop, map or lter them, and do all other sorts of things.
Set Algebra
As the name implies, Set is closely related to the mathematical concept of a set; it
supports all common set operations you learned in math class. For example, we can
subtract one set from another:
let iPods: Set = ["iPod touch", "iPod nano", "iPod mini",
"iPod shuffle", "iPod classic"]
let discontinuedIPods: Set = ["iPod mini", "iPod classic",
"iPod nano", "iPod shuffle"]
let currentIPods = iPods.subtracting(discontinuedIPods) // ["iPod touch"]
We can also form the intersection of two sets, i.e. find all elements that are in both:
let touchscreen: Set = ["iPhone", "iPad", "iPod touch", "iPod nano"]
let iPodsWithTouch = iPods.intersection(touchscreen)
// ["iPod touch", "iPod nano"]
Or, we can form the union of two sets, i.e. combine them into one (removing duplicates,
of course):
var discontinued: Set = ["iBook", "PowerBook", "Power Mac"]
discontinued.formUnion(discontinuedIPods)
discontinued
/*
["iPod shuffle", "Power Mac", "iBook", "iPod classic", "PowerBook",
"iPod mini", "iPod nano"]
*/
Here, we used the mutating variant formUnion to mutate the original set (which, as a
result, must be declared with var). Almost all set operations have both non-mutating
and mutating forms, and the latter have a form prefix. For even more set operations,
check out the SetAlgebra protocol.
Index Sets and Character Sets
Set and OptionSet are the only types in the standard library that conform to SetAlgebra,
but this protocol is also adopted by two interesting types in Foundation: IndexSet and
CharacterSet. Both of these date back to a time long before Swift was a thing. The way
these and other Objective-C classes are now bridged into Swift as fully featured value
types — adopting common standard library protocols in the process — is great because
they’ll instantly feel familiar to Swift developers.
IndexSet represents a set of positive integer values. You can, of course, use a Set<Int> for
this task, but IndexSet is more storage efficient because it uses a list of ranges internally.
Say you have a table view with 1,000 elements and you want to use a set to manage the
indices of the rows the user has selected. A Set<Int> needs to store up to 1,000 elements,
depending on how many rows are selected. An IndexSet, on the other hand, stores
continuous ranges, so a selection of the first 500 rows in the table only takes two
integers to store (the selection’s lower and upper bounds).
However, as a user of an IndexSet, you don’t have to worry about the internal structure,
as it’s completely hidden behind the familiar SetAlgebra and Collection interfaces.
(Unless you want to work on the ranges directly, that is. IndexSet exposes a view to them
via its rangeView property, which itself is a collection.) For example, you can add a few
ranges to an index set and then map over the indices as if they were individual
members:
var indices = IndexSet()
indices.insert(integersIn: 1..<5)
indices.insert(integersIn: 11..<15)
let evenIndices = indices.filter { $0 % 2 == 0 } // [2, 4, 12, 14]
CharacterSet is an equally efficient way to store a set of Unicode code points. It’s often
used to check if a particular string only contains characters from a specific character
subset, such as alphanumerics or decimalDigits. However, unlike IndexSet, CharacterSet
isn’t a collection. The name CharacterSet, imported from Objective-C, is unfortunate in
Swift because CharacterSet isn’t compatible with Swift’s Character type. A better name
would be UnicodeScalarSet. We’ll talk more about CharacterSet in the chapter on
Strings.
Using Sets Inside Closures
Dictionaries and sets can be very handy data structures to use inside your functions,
even when you’re not exposing them to the caller. For example, if we want to write an
extension on Sequence to retrieve all unique elements in the sequence, we could easily
put the elements in a set and return its contents. However, that won’t be stable: because
a set has no defined order, the input elements might get reordered in the result. To fix
this, we can write an extension that maintains the order by using an internal Set for
bookkeeping:
extension Sequence where Element: Hashable {
func unique() -> [Element] {
var seen: Set<Element> = []
return filter { element in
if seen.contains(element) {
return false
} else {
seen.insert(element)
return true
}
}
}
}
[1,2,3,12,1,3,4,5,6,4,6].unique() // [1, 2, 3, 12, 4, 5, 6]
The method above allows us to find all unique elements in a sequence while still
maintaining the original order (with the constraint that the elements must be Hashable).
Inside the closure we pass to lter, we refer to the variable seen that we defined outside
the closure, thus maintaining state over multiple iterations of the closure. In the chapter
on Functions, we’ll look at this technique in more detail.
Other documents randomly have
different content
Advanced Swift Updated For Swift 5 Chris Eidhof
Advanced Swift Updated For Swift 5 Chris Eidhof
Advanced Swift Updated For Swift 5 Chris Eidhof
The Project Gutenberg eBook of Addison
This ebook is for the use of anyone anywhere in the United States
and most other parts of the world at no cost and with almost no
restrictions whatsoever. You may copy it, give it away or re-use it
under the terms of the Project Gutenberg License included with this
ebook or online at www.gutenberg.org. If you are not located in the
United States, you will have to check the laws of the country where
you are located before using this eBook.
Title: Addison
Author: William John Courthope
Release date: November 27, 2012 [eBook #41496]
Most recently updated: October 23, 2024
Language: English
Credits: E-text prepared by the Online Distributed Proofreading Team
(http://www.pgdp.net) from page images generously made
available by Internet Archive (http://archive.org)
*** START OF THE PROJECT GUTENBERG EBOOK ADDISON ***
The Project Gutenberg eBook, Addison, by William John Courthope
Note: Images of the original pages are available through Internet
Archive. See http://archive.org/details/addison_00cour
English Men of Letters
EDITED BY JOHN MORLEY
ADDISON
BY
W. J. COURTHOPE
HARPER & BROTHERS PUBLISHERS
NEW YORK AND LONDON
1902
ENGLISH MEN OF LETTERS.
Edited by John Morley.
Johnson Leslie Stephen.
Gibbon J. C. Morison.
Scott R. H. Hutton.
Shelley J. A. Symonds.
Hume T. H. Huxley.
Goldsmith William Black.
Defoe William Minto.
Burns J. C. Shairp.
Spenser R. W. Church.
Thackeray Anthony Trollope.
Burke John Morley.
Milton Mark Pattison.
Hawthorne Henry James, Jr.
Southey E. Dowden.
Chaucer A. W. Ward.
Bunyan J. A. Froude.
Cowper Goldwin Smith.
Pope Leslie Stephen.
Byron John Nichol.
Locke Thomas Fowler.
Wordsworth F. Myers.
Dryden G. Saintsbury.
Landor Sidney Colvin.
De Quincey David Masson.
Lamb Alfred Ainger.
Bentley R. C. Jebb.
Dickens A. W. Ward.
Gray E. W. Gosse.
Swift Leslie Stephen.
Sterne H. D. Traill.
Macaulay J. Cotter Morison.
Fielding Austin Dobson.
Sheridan Mrs. Oliphant.
Addison W. J. Courthope.
Bacon R. W. Church.
Coleridge H. D. Traill.
Sir Philip Sidney J. A. Symonds.
Keats Sidney Colvin.
Carlyle John Nichol.
12mo, Cloth, 75 cents per volume.
Other volumes in preparation.
Published by HARPER & BROTHERS, New York.
☞ Any of the above works will be sent by mail, postage prepaid, to
any part
of the United States, Canada, or Mexico, on receipt of the price.
CONTENTS.
PAGE
CHAPTER I.
The State of English Society and Letters after the Restoration 1
CHAPTER II.
Addison’s Family and Education 21
CHAPTER III.
Addison on His Travels 38
CHAPTER IV.
His Employment in Affairs of State 53
CHAPTER V.
The “Tatler” and “Spectator” 78
CHAPTER VI.
“Cato” 110
CHAPTER VII.
Addison’s Quarrel with Pope 125
CHAPTER VIII.
The Last Years of His Life 139
CHAPTER IX.
The Genius of Addison 153
ADDISON.
CHAPTER I.
THE STATE OF ENGLISH SOCIETY AND
LETTERS AFTER THE RESTORATION.
Of the four English men of letters whose writings most fully embody
the spirit of the eighteenth century, the one who provides the
biographer with the scantiest materials is Addison. In his Journal to
Stella, his social verses, and his letters to his friends, we have a vivid
picture of those relations with women and that protracted suffering
which invest with such tragic interest the history of Swift. Pope, by
the publication of his own correspondence, has enabled us, in a way
that he never intended, to understand the strange moral twist which
distorted a nature by no means devoid of noble instincts. Johnson
was fortunate in the companionship of perhaps the best biographer
who ever lived. But of the real life and character of Addison scarcely
any contemporary record remains. The formal narrative prefixed to
his works by Tickell is, by that writer’s own admission, little more
than a bibliography. Steele, who might have told us more than any
man about his boyhood and his manner of life in London, had
become estranged from his old friend before his death. No writer
has taken the trouble to preserve any account of the wit and wisdom
that enlivened the “little senate” at Button’s. His own letters are, as
a rule, compositions as finished as his papers in the Spectator.
Those features in his character which excite the greatest interest
have been delineated by the hand of an enemy—an enemy who
possessed an unrivalled power of satirical portrait-painting, and was
restrained by no regard for truth from creating in the public mind
such impressions about others as might serve to heighten the
favourable opinion of himself.
This absence of dramatic incident in Addison’s life would lead us
naturally to conclude that he was deficient in the energy and passion
which cause a powerful nature to leave a mark upon its age. Yet
such a judgment would certainly be erroneous. Shy and reserved as
he was, the unanimous verdict of his most illustrious contemporaries
is decisive as to the respect and admiration which he excited among
them. The man who could exert so potent an influence over the
mercurial Steele, who could fascinate the haughty and cynical
intellect of Swift, whose conversation, by the admission of his satirist
Pope, had in it something more charming than that of any other
man; of whom it was said that he might have been chosen king if he
wished it; such a man, though to the coarse perception of
Mandeville he might have seemed no more than “a parson in a tye-
wig,” can hardly have been deficient in force of character.
Nor would it have been possible for a writer distinguished by mere
elegance and refinement to leave a lasting impress on the literature
and society of his country. In one generation after another, men
representing opposing elements of rank, class, interest, and taste,
have agreed in acknowledging Addison’s extraordinary merits.
“Whoever wishes,” says Johnson—at the end of a biography strongly
coloured with the prepossessions of a semi-Jacobite Tory—“whoever
wishes to attain an English style, familiar but not coarse, and elegant
but not ostentatious, must give his days and nights to the volumes
of Addison.” “Such a mark of national respect,” says Macaulay, the
best representative of middle-class opinion in the present century,
speaking of the statue erected to Addison in Westminster Abbey,
“was due to the unsullied statesman, to the accomplished scholar, to
the master of pure English eloquence, to the consummate painter of
life and manners. It was due, above all, to the great satirist who
alone knew how to use ridicule without abusing it; who, without
inflicting a wound, effected a great social reform, and who
reconciled wit and virtue after a long and disastrous separation,
during which wit had been led astray by profligacy, and virtue by
fanaticism.”
This verdict of a great critic is accepted by an age to which the
grounds of it are, perhaps, not very apparent. The author of any
ideal creation—a poem, a drama, or a novel—has an imprescriptible
property in the fame of his work. But to harmonise conflicting social
elements, to bring order out of chaos in the sphere of criticism, to
form right ways of thinking about questions of morals, taste, and
breeding, are operations of which the credit, though it is certainly to
be ascribed to particular individuals, is generally absorbed by society
itself. Macaulay’s eulogy is as just as it is eloquent, but the pages of
the Spectator alone will hardly show the reader why Addison should
be so highly praised for having reconciled wit with virtue. Nor,
looking at him as a critic, will it appear a great achievement to have
pointed out to English society the beauties of Paradise Lost, unless it
be remembered that the taste of the preceding generation still
influenced Addison’s contemporaries, and that in that generation
Cowley was accounted a greater poet than Milton.
To estimate Addison at his real value we must regard him as the
chief architect of Public Opinion in the eighteenth century. But here
again we are met by an initial difficulty, because it has become
almost a commonplace of contemporary criticism to represent the
eighteenth century as a period of sheer destruction. It is tacitly
assumed by a school of distinguished philosophical writers that we
have arrived at a stage in the world’s history in which it is possible to
take a positive and scientific view of human affairs. As it is of course
necessary that from such a system all belief in the supernatural shall
be jealously excluded, it has not seemed impossible to write the
history of Thought itself in the eighteenth century. And in tracing the
course of this supposed continuous stream it is natural that all the
great English writers of the period should be described as in one way
or another helping to pull down, or vainly to strengthen, the
theological barriers erected by centuries of bigotry against the
irresistible tide of enlightened progress.
It would be of course entirely out of place to discuss here the merits
of this new school of history. Those who consider that, whatever
glimpses we may obtain of the law and order of the universe, man
is, as he always has been and always will be, a mystery to himself,
will hardly allow that the operations of the human spirit can be
traced in the dissecting-room. But it is, in any case, obvious that to
treat the great imaginative writers of any age as if they were only
mechanical agents in an evolution of thought is to do them grave
injustice. Such writers are, above all things, creative. Their first aim
is to “show the very age and body of the time his form and
pressure.” No work of the eighteenth century, composed in a
consciously destructive spirit, has taken its place among the
acknowledged classics of the language. Even the Tale of a Tub is to
be regarded as a satire upon the aberrations of theologians from
right reason, not upon the principles of Christianity itself. The Essay
on Man has, no doubt, logically a tendency towards Deism, but
nobody ever read the poem for the sake of its philosophy; and it is
well known that Pope was much alarmed when it was pointed out to
him that his conclusions might be represented as incompatible with
the doctrines of revealed religion.
The truth indeed seems to be the exact converse of what is alleged
by the scientific historians. So far from the eighteenth century in
England being an age of destructive analysis, its energies were
chiefly devoted to political, social, and literary reconstruction.
Whatever revolution in faith and manners the English nation had
undergone had been the work of the two preceding centuries, and
though the historic foundations of society remained untouched, the
whole form of the superstructure had been profoundly modified.
“So tenacious are we,” said Burke, towards the close of the last
century, “of our old ecclesiastical modes and fashions of institution
that very little change has been made in them since the fourteenth
or fifteenth centuries, adhering in this particular as in all else to our
old settled maxim never entirely nor at once to depart from
antiquity. We found these institutions on the whole favourable to
morality and discipline, and we thought they were susceptible of
amendment without altering the ground. We thought they were
capable of receiving and meliorating, and, above all, of preserving
the accessories of science and literature as the order of Providence
should successively produce them. And after all, with this Gothic and
monkish education (for such it is the groundwork), we may put in
our claim to as ample and early a share in all the improvements in
science, in arts, and in literature which have illuminated the modern
world as any other nation in Europe. We think one main cause of
this improvement was our not despising the patrimony of knowledge
which was left us by our forefathers.”
All this is, in substance, true of our political as well as our
ecclesiastical institutions. And yet, when Burke wrote, the great
feudal and mediæval structure of England had been so transformed
by the Wars of the Roses, the Reformation, the Rebellion, and the
Revolution, that its ancient outlines were barely visible. In so far,
therefore, as his words seem to imply that the social evolution he
describes was produced by an imperceptible and almost mechanical
process of national instinct, the impression they tend to create is
entirely erroneous.
If we have been hitherto saved from such corruption as undermined
the republics of Italy, from the religious wars that so long enfeebled
and divided Germany, and from the Revolution that has severed
modern France from her ancient history, thanks for this are due
partly, no doubt, to favouring conditions of nature and society, but
quite as much to the genius of great individuals who prepared the
mind of the nation for the gradual assimilation of new ideas. Thus
Langland and Wycliffe and their numerous followers, long before the
Reformation, had so familiarised the minds of the people with their
ideas of the Christian religion that the Sovereign was able to assume
the Headship of the Church without the shock of a social convulsion.
Fresh feelings and instincts grew up in the hearts of whole classes of
the nation without at first producing any change in outward habits of
life, and even without arousing a sense of their logical incongruity.
These mixed ideas were constantly brought before the imagination
in the works of the poets. Shakespeare abounds with passages in
which, side by side with the old feudal, monarchical, catholic, and
patriotic instincts of Englishmen, we find the sentiments of the
Italian Renaissance. Spenser conveys Puritan doctrines sometimes
by the mouth of shepherds, whose originals he had found in
Theocritus and Virgil; sometimes under allegorical forms derived
from books of chivalry and the ceremonial of the Catholic Church.
Milton, the most rigidly Calvinistic of all the English poets in his
opinions, is also the most severely classical in his style.
It was the task of Addison to carry on the reconciling traditions of
our literature. It is his praise to have accomplished his task under
conditions far more difficult than any that his predecessors had
experienced. What they had done was to give instinctive and
characteristic expression to the floating ideas of the society about
them; what Addison and his contemporaries did was to found a
public opinion by a conscious effort of reason and persuasion. Before
the Civil Wars there had been at least no visible breach in the
principle of Authority in Church and State. At the beginning of the
eighteenth century constituted authority had been recently
overthrown; one king had been beheaded, another had been
expelled; the Episcopalian form of Church Government had been
violently displaced in favour of the Presbyterian, and had been with
almost equal violence restored. Whole classes of the population had
been drawn into opposing camps during the Civil War, and still stood
confronting each other with all the harsh antagonism of sentiment
inherited from that conflict. Such a bare summary alone is sufficient
to indicate the nature of the difficulties Addison had to encounter in
his efforts to harmonise public opinion; but a more detailed
examination of the state of society after the Restoration is required
to place in its full light the extraordinary merits of the success that
he achieved.
There was, to begin with, a vehement opposition between town and
country. In the country the old ideas of Feudalism, modified by
circumstances, but vigorous and deep-rooted, still prevailed. True,
the military system of land-tenure had disappeared with the
Restoration, but it was not so with the relations of life, and the
habits of thought and feeling which the system had created. The
features of surviving Feudalism have been inimitably preserved for
us in the character of Sir Roger de Coverley. Living in the patriarchal
fashion, in the midst of tenants and retainers, who looked up to him
as their chief, and for whose welfare and protection he considered
himself responsible, the country gentleman valued above all things
the principle of Loyalty. To the moneyed classes in the towns he was
instinctively opposed; he regarded their interests, both social and
commercial, as contrary to his own; he looked with dislike and
suspicion on the economical principles of government and conduct
on which these classes naturally rely. Even the younger sons of
county families had in Addison’s day abandoned the custom,
common enough in the feudal times, of seeking their fortune in
trade. Many a Will Wimble now spent his whole life in the country,
training dogs for his neighbours, fishing their streams, making whips
for their young heirs, and even garters for their wives and
daughters.[1]
The country gentlemen were confirmed in these ideas by the
difficulties of communication. During his visit to Sir Roger de
Coverley the Spectator observed the extreme slowness with which
fashions penetrated into the country; and he noticed, too, that party
spirit was much more violent there than in the towns. The learning
of the clergy, many of whom resided with the country squires as
chaplains, was of course enlisted on the Tory side, and supplied it
with arguments which the body of the party might perhaps have
found it difficult to discover, or at least to express, for themselves.
For Tory tastes undoubtedly lay generally rather in the direction of
sport than of books. Sir Roger seems to be as much above the
average level of his class as Squire Western is certainly below it:
perhaps the Tory fox-hunter of the Freeholder, though somewhat
satirically painted, is a fair representative of the society which had its
headquarters at the October Club, and whose favourite poet was
Tom D’Urfey.
The commercial and professional classes, from whom the Whigs
derived their chief support, of course predominated in the towns,
and their larger opportunities of association gave them an influence
in affairs which compensated for their inferiority in numbers. They
lacked, however, what the country party possessed, a generous ideal
of life. Though many of them were connected with the Presbyterian
system, their common sense made them revolt from its rigidity, while
at the same time their economical principles failed to supply them
with any standard that could satisfy the imagination. Sir Andrew
Freeport excites in us less interest than any member of the
Spectator’s Club. There was not yet constituted among the upper
middle classes that mixed conception of good feeling, good
breeding, and good taste which we now attach to the name of
“gentleman.”
Two main currents of opinion divided the country, to one of which a
man was obliged to surrender himself if he wished to enjoy the
pleasures of organised society. One of these was Puritanism, but this
was undoubtedly the less popular, or at least the less fashionable. A
protracted experience of Roundhead tyranny under the Long
Parliament had inclined the nation to believe that almost any form of
Government was preferable to that of the Saints. The Puritan, no
longer the mere sectarian, as in the days of Elizabeth and James I.,
somewhat ridiculous in the extravagance of his opinions, but
respectable from the constancy with which he maintained them, had
ruled over them as a taskmaster, and had forced them, as far as he
could by military violence, to practise the asceticism to which monks
and nuns had voluntarily submitted themselves. The most innocent
as well as the most brutal diversions of the people were sacrificed to
his spiritual pride. As Macaulay well says, he hated bear-baiting, not
because it gave pain to the bear, but because it gave pleasure to the
spectator. The tendency of his creed was, in fact, anti-social. Beauty
in his eyes was a snare, and pleasure a sin; the only mode of social
intercourse which he approved was a sermon.
On the other hand, the habits of the Court, which gave the tone to
all polite society, were almost equally distasteful to the instincts of
the people. It was inevitable that the inclinations of Charles II.
should be violently opposed to every sentiment of the Puritans.
While he was in the power of the Scots he had been forced into
feigned compliance with Presbyterian rites; the Puritans had put his
father to death, and had condemned himself to many years of exile
and hardship in Catholic countries. He had returned to his own land
half French in his political and religious sympathies, and entirely so
in his literary tastes. To convert and to corrupt those of his subjects
who immediately surrounded him was an easy matter. “All by the
king’s example lived and loved.” Poets, painters, and actors were
forward to promote principles viewed with favour by their sovereign
and not at all disagreeable to themselves. An ingenious philosopher
elevated Absolutism into an intellectual and moral system, the
consequence of which was to encourage the powerful in the
indulgence of every selfish instinct. As the Puritans had oppressed
the country with a system of inhuman religion and transcendental
morality, so now, in order to get as far from Puritanism as possible,
it seemed necessary for every one aspiring to be thought a
gentleman to avow himself an atheist or a debauchee.
The ideas of the man in the mode after the Restoration are
excellently hit off in one of the fictitious letters in the Spectator:
“I am now between fifty and sixty, and had the honour to
be well with the first men of taste and gallantry in the
joyous reign of Charles the Second. As for yourself, Mr.
Spectator, you seem with the utmost arrogance to
undermine the very fundamentals upon which we
conducted ourselves. It is monstrous to set up for a man
of wit and yet deny that honour in a woman is anything
but peevishness, that inclination is not the best rule of life,
or virtue and vice anything else but health and disease.
We had no more to do but to put a lady in a good humour,
and all we could wish followed of course. Then, again,
your Tully and your discourses of another life are the very
bane of mirth and good humour. Prythee, don’t value
thyself on thy reason at that exorbitant rate and the
dignity of human nature; take my word for it, a setting
dog has as good reason as any man in England.”[2]
While opinions, which from different sides struck at the very roots of
society, prevailed both in the fashionable and religious portions of
the community, it was inevitable that Taste should be hopelessly
corrupt. All the artistic and literary forms which the Court favoured
were of the romantic order, but it was romance from which beauty
and vitality had utterly disappeared. Of the two great principles of
ancient chivalry, Love and Honour, the last notes of which are heard
in the lyrics of Lovelace and Montrose, one was now held to be non-
existent, and the other was utterly perverted. The feudal spirit had
surrounded woman with an atmosphere of mystical devotion, but in
the reign of Charles II. the passion of love was subjected to the
torturing treatment then known as “wit.” Cowley and Waller seem to
think that when a man is in love the energy of his feelings is best
shown by discovering resemblances between his mistress and those
objects in nature to which she is apparently most unlike.
The ideal of Woman, as she is represented in the Spectator, adding
grace, charity, and refinement to domestic life, had still to be
created. The king himself, the presumed mirror of good taste, was
notoriously under the control of his numerous mistresses; and the
highest notion of love which he could conceive was gallantry. French
romances were therefore generally in vogue. All the casuistry of love
which had been elaborated by Mademoiselle de Scudery was
reproduced with improvements by Mrs. Aphra Behn. At the same
time, as usually happens in diseased societies, there was a general
longing to cultivate the simplicity of the Golden Age, and the
consequence was that no person, even in the lower grades of
society, who pretended to any reading, ever thought of making love
in his own person. The proper tone of feeling was not acquired till he
had invested himself with the pastoral attributes of Damon and
Celadon, and had addressed his future wife as Amarantha or Phyllis.
The tragedies of the period illustrate this general inclination to
spurious romance. If ever there was a time when the ideal of
monarchy was degraded, and the instincts of chivalrous action
discouraged, it was in the reign of Charles II. Absorbed as he was in
the pursuit of pleasure, the king scarcely attempted to conceal his
weariness when obliged to attend to affairs of State. He allowed the
Dutch fleet to approach his capital and to burn his own ships of war
on the Thames; he sold Dunkirk to the French; hardly any action in
his life evinces any sense of patriotism or honour. And yet we have
only to glance at Johnson’s Life of Dryden to see how all the
tragedies of the time turn on the great characters, the great actions,
the great sufferings of princes. The Elizabethan drama had exhibited
man in every degree of life and with every variety of character; the
playwright of the Restoration seldom descended below such themes
as the conquest of Mexico or Granada, the fortunes of the Great
Mogul, and the fate of Hannibal. This monotony of subject was
doubtless in part the result of policy, for in pitying the fortunes of
Montezuma the imagination of the spectator insensibly recalled
those of Charles the Second.
Everything in these tragedies is unreal, strained, and affected. In
order to remove them as far as possible from the language of
ordinary life they are written in rhyme, while the astonishment of the
audience is raised with big swelling words, which vainly seek to hide
the absence of genuine feeling. The heroes tear their passion to
tatters because they think it heroic to do so; their flights into the
sublime generally drop into the ridiculous; instead of holding up the
mirror to nature, their object is to depart as far as possible from
common sense. Nothing exhibits more characteristically the utterly
artificial feeling, both of the dramatists and the spectators, than the
habit which then prevailed of dismissing the audience after a tragic
play with a witty epilogue. On one occasion, Nell Gwynne, in the
character of St. Catherine, was, at the end of the play, left for dead
upon the stage. Her body having to be removed, the actress
suddenly started to her feet, exclaiming,
“Hold! are you mad? you damned confounded dog,
I am to rise and speak the epilogue!”[3]
By way of compensation, however, the writers of the period poured
forth their real feelings without reserve in their comedies. So great,
indeed, is the gulf that separates our own manners from theirs, that
some critics have endeavoured to defend the comic dramatists of the
Restoration against the moralists on the ground that their
representations of Nature are entirely devoid of reality. Charles
Lamb, who loved all curiosities, and the Caroline comedians among
the number, says of them:
“They are a world of themselves almost as much as fairy-
land. Take one of their characters, male or female (with
few exceptions they are alike), and place it in a modern
play, and my virtuous indignation shall rise against the
profligate wretch as warmly as the Catos of the pit could
desire, because in a modern play I am to judge of the
right and the wrong. The standard of police is the
measure of political justice. The atmosphere will blight it;
it cannot live here. It has got into a moral world, where it
has no business, from which it must needs fall headlong—
as dizzy and incapable of making a stand as a
Swedenborgian bad spirit that has wandered unawares
into his sphere of Good Men or Angels. But in its own
world do we feel the creature is so very bad? The Fainalls
and Mirabels, the Dorimants and Lady Touchwoods, in
their own sphere do not offend my moral sense; in fact,
they do not appeal to it at all. They seem engaged in their
proper element. They break through no laws or
conscientious restraints. They know of none. They have
got out of Christendom into the land of-what shall I call it?
—of cuckoldry—the Utopia of gallantry, where pleasure is
duty and the manners perfect freedom. It is altogether a
speculative scene of things, which has no reference
whatever to the world that is.”
This is a very happy description of the manner in which the plays of
Etherege, Shadwell, Wycherley, and Congreve affect us to-day; and
it is no doubt superfluous to expend much moral indignation on
works which have long since lost their power to charm: comedies in
which the reader finds neither the horseplay of Aristophanes, nor the
nature of Terence, nor the poetry of Shakespeare; in which there is
not a single character that arouses interest, or a situation that
spontaneously provokes laughter; in which the complications of plot
are produced by the devices of fine gentlemen for making cuckolds
of citizens, and the artifices of wives to dupe their husbands; in
which the profuse wit of the dialogue might excite admiration, if it
were possible to feel the smallest interest in the occasion that
produced it. But to argue that these plays never represented any
state of existing society is a paradox which chooses to leave out of
account the contemporary attack on the stage made by Jeremy
Collier, the admissions of Dryden, and all those valuable glimpses
into the manners of our ancestors which are afforded by the
prologues of the period.
It is sufficient to quote against Lamb the witty and severe criticism
of Steele in the Spectator, upon Etherege’s Man of the Mode:
“It cannot be denied but that the negligence of everything which
engages the attention of the sober and valuable part of mankind
appears very well drawn in this piece. But it is denied that it is
necessary to the character of a fine gentleman that he should in that
manner trample upon all order and decency. As for the character of
Dorimant, it is more of a coxcomb than that of Fopling. He says of
one of his companions that a good correspondence between them is
their mutual interest. Speaking of that friend, he declares their being
much together ‘makes the women think the better of his
understanding, and judge more favourably of my reputation. It
makes him pass upon some for a man of very good sense, and me
upon others for a very civil person.’ This whole celebrated piece is a
perfect contradiction to good manners, good sense, and common
honesty; and as there is nothing in it but what is built upon the ruin
of virtue and innocence, according to the notion of virtue in this
comedy, I take the shoemaker to be in reality the fine gentleman of
the play; for it seems he is an atheist, if we may depend upon his
character as given by the orange-woman, who is herself far from
being the lowest in the play. She says of a fine man who is
Dorimant’s companion, ‘there is not such another heathen in the
town except the shoemaker.’ His pretension to be the hero of the
drama appears still more in his own description of his way of living
with his lady. ‘There is,’ says he, ‘never a man in the town lives more
like a gentleman with his wife than I do. I never mind her motions;
she never inquires into mine. We speak to one another civilly; hate
one another heartily; and, because it is vulgar to lie and soak
together, we have each of us our several settle-beds.’
“That of ‘soaking together’ is as good as if Dorimant had spoken it
himself; and I think, since he puts human nature in as ugly a form
as the circumstances will bear, and is a staunch unbeliever, he is
very much wronged in having no part of the good fortune bestowed
in the last act. To speak plain of this whole work, I think nothing but
being lost to a sense of innocence and virtue can make any one see
this comedy without observing more frequent occasion to move
sorrow and indignation than mirth and laughter. At the same time I
allow it to be nature, but it is nature in its utmost corruption and
degeneracy.”[4]
The truth is, that the stage after the Restoration reflects only too
faithfully the manners and the sentiments of the only society which
at that period could boast of anything like organisation. The press,
which now enables public opinion to exercise so powerful a control
over the manners of the times, had then scarcely an existence. No
standard of female honour restrained the license of wit and
debauchery. If the clergy were shocked at the propagation of ideas
so contrary to the whole spirit of Christianity, their natural impulse to
reprove them was checked by the fear that an apparent
condemnation of the practices of the Court might end in the triumph
of their old enemies, the Puritans. All the elements of an old and
decaying form of society that tended to atheism, cynicism, and
dissolute living, exhibited themselves, therefore, in naked
shamelessness on the stage. The audiences in the theatres were
equally devoid of good manners and good taste; they did not
hesitate to interrupt the actors in the midst of a serious play, while
they loudly applauded their obscene allusions. So gross was the
character of comic dialogue that women could not venture to appear
at a comedy without masks, and under these circumstances the
theatre became the natural centre for assignations. In such an
atmosphere women readily cast off all modesty and reserve; indeed,
the choicest indecencies of the times are to be found in the
epilogues to the plays, which were always assigned to the female
actors.
It at first sight seems remarkable that a society inveterately corrupt
should have contained in itself such powers of purification and
vitality as to discard the literary garbage of the Restoration period in
favour of the refined sobriety which characterises the writers of
Queen Anne’s reign. But, in fact, the spread of the infection was
confined within certain well-marked limits. The Court moved in a
sphere apart, and was altogether too light and frivolous to exert a
decided moral influence on the great body of the nation. The
country gentlemen, busied on their estates, came seldom to town;
the citizens, the lawyers, and the members of the other professions
steadily avoided the theatre, and regarded with equal contempt the
moral and literary excesses of the courtiers. Among this class,
unrepresented at present in the world of letters, except, perhaps, by
antiquarians like Selden, the foundations of sound taste were being
silently laid. The readers of the nation had hitherto been almost
limited to the nobility. Books were generally published by
subscription, and were dependent for their success on the favour
with which they were received by the courtiers. But, after the
subsidence of the Civil War, the nation began to make rapid strides
in wealth and refinement, and the moneyed classes sought for
intellectual amusement in their leisure hours. Authors by degrees
found that they might look for readers beyond the select circle of
their aristocratic patrons; and the book-seller, who had hitherto
calculated his profits merely by the commission he might obtain on
the sale of books, soon perceived that they were becoming valuable
as property. The reign of Charles II. is remarkable not only for the
great increase in the number of the licensed printers in London, but
for the appearance of the first of the race of modern publishers,
Jacob Tonson.
The portion of society whose tastes the publishers undertook to
satisfy was chiefly interested in history, poetry, and criticism. It was
this for which Dryden composed his Miscellany, this to which he
addressed the admirable critical essays which precede his
Translations from the Latin Poets and his Versifications of Chaucer,
and this which afterwards gave the main support to the Tatler and
the Spectator. Ignorant of the writings of the great classical authors,
as well as of the usages of polite society, these men were
nevertheless robust and manly in their ideas, and were eager to
form for themselves a correct standard of taste by reference to the
best authorities. Though they turned with repugnance from the
playhouse and from the morals of the Court, they could not avoid
being insensibly affected by the tone of grace and elegance which
prevailed in Court circles. And in this respect, if in no other, our
gratitude is due to the Caroline dramatists, who may justly claim to
be the founders of the social prose style in English literature. Before
them English prose had been employed, no doubt, with music and
majesty by many writers; but the style of these is scarcely
representative; they had used the language for their own elevated
purposes, without, however, attempting to give it that balanced
fineness and subtlety which makes it a fitting instrument for
conveying the complex ideas of an advanced stage of society.
Dryden, Wycherley, and their followers, impelled by the taste of the
Court to study the French language, brought to English composition
a nicer standard of logic and a more choice selection of language,
while the necessity of pleasing their audiences with brilliant dialogue
made them careful to give their sentences that well-poised structure
which Addison afterwards carried to perfection in the Spectator.
By this brief sketch the reader may be enabled to judge of the
distracted state of society, both in politics and taste, in the reign of
Charles II. On the one side, the Monarchical element in the
Constitution was represented by the Court Party, flushed with the
recent restoration; retaining the old ideas and principles of
absolutism which had prevailed under James I., without being able
to perceive their inapplicability to the existing nature of things;
feeding its imagination alternately on sentiments derived from the
decayed spirit of chivalry, and on artistic representations of
fashionable debauchery in its most open form—a party which, while
it fortunately preserved the traditions of wit, elegance, and gaiety of
style, seemed unaware that these qualities could be put to any other
use than the mitigation of an intolerable ennui. On the other side,
the rising power of Democracy found its representatives in austere
Republicans opposed to all institutions in Church and State that
seemed to obstruct their own abstract principles of government;
gloomy fanatics, who, with an intense intellectual appreciation of
eternal principles of religion and morality, sought to sacrifice to their
system the most permanent and even innocent instincts of human
nature. Between the two extreme parties was the unorganised body
of the nation, grouped round old customs and institutions, rapidly
growing in wealth and numbers, conscious of the rise in their midst
of new social principles, but perplexed how to reconcile these with
time-honoured methods of religious, political, and literary thought.
To lay the foundations of sound opinion among the people at large;
to prove that reconciliation was possible between principles hitherto
exhibited only in mutual antagonism; to show that under the English
Constitution monarchy, aristocracy, and democracy might all be
harmonised, that humanity was not absolutely incompatible with
religion or morality with art, was the task of the statesmen, and still
more of the men of letters, of the early part of the eighteenth
century.
Advanced Swift Updated For Swift 5 Chris Eidhof
CHAPTER II.
ADDISON’S FAMILY AND EDUCATION.
Joseph Addison was born on the 1st of May, 1672. He was the eldest
son of Lancelot Addison, at the time of his birth rector of Milston,
near Amesbury, in Wiltshire, and afterwards Dean of Lichfield. His
father was a man of character and accomplishments. Educated at
Oxford, while that University was under the control of the famous
Puritan Visitation, he made no secret of his contempt for principles
to which he was forced to submit, or of his preferences for Monarchy
and Episcopacy. His boldness was not agreeable to the University
authorities, and being forced to leave Oxford, he maintained himself
for a time near Petworth, in Sussex, by acting as chaplain or tutor in
families attached to the Royalist cause. After the Restoration he
obtained the appointment of chaplain to the garrison of Dunkirk, and
when that town was ceded to France in 1662, he was removed in a
similar capacity to Tangier. Here he remained eight years, but,
venturing on a visit to England, his post was bestowed upon another,
and he would have been left without resources had not one of his
friends presented him with the living of Milston, valued at £120 a
year. With the courage of his order he thereupon took a wife, Jane,
daughter of Dr. Nathaniel Gulston, and sister of William Gulston,
Bishop of Bristol, by whom he had six children, three sons and three
daughters, all born at Milston. In 1675 he was made a prebendary of
Salisbury Cathedral and Chaplain-in-Ordinary to the King; and in
1683 he was promoted to the Deanery of Lichfield, as a reward for
his services at Tangier, and out of consideration of losses which he
had sustained by a fire at Milston. His literary reputation stood high,
and it is said that he would have been made a bishop, if his old zeal
for legitimacy had not prompted him to manifest in the Convocation
of 1689 his hostility to the Revolution. He died in 1703.
Lancelot was a writer at once voluminous and lively. In the latter
part of his life he produced several treatises on theological subjects,
the most popular of which was called An Introduction to the
Sacrament. This book passed through many editions. The doctrine it
contains leans rather to the Low Church side. But much the most
characteristic of his writings were his works on Mahommedanism
and Judaism, the results of his studies during his residence in
Barbary. These show not only considerable industry and research
and powers of shrewd observation, but that genuine literary faculty
which enables a writer to leave upon a subject of a general nature
the impression of his own character. While there is nothing forced or
exaggerated in his historical style, a vein of allegory runs through
the narrative of the Revolutions of the Kingdoms of Fez and
Morocco, which must have had a piquant flavour for the orthodox
English reader of that day. Recollections of the Protectorate would
have taken nothing of its vividness from the portrait of the Moorish
priest who “began to grow into reputation with the people by reason
of his high pretensions to piety and fervent zeal for their law,
illustrated by a stubborn rigidity of conversation and outward
sanctity of life.” When the Zeriffe, with ambitious designs on the
throne, sent his sons on a pilgrimage to Mecca, the religious
buffooneries practised by the young men must have recalled to the
reader circumstances more recent and personal than those which
the author was apparently describing. “Much was the reverence and
reputation of holiness which they thereby acquired among the
superstitious people, who could hardly be kept from kissing their
garments and adoring them as saints, while they failed not in their
parts, but acted as much devotion as high contemplative looks, deep
sighs, tragical gestures, and other passionate interjections of
holiness could express. ‘Allah, allah!’ was their doleful note, their
sustenance the people’s alms.” And when these impostors had
inveigled the King of Fez into a religious war, the description of those
who “mistrusted their own safety, and began, but too late, to repent
Welcome to our website – the perfect destination for book lovers and
knowledge seekers. We believe that every book holds a new world,
offering opportunities for learning, discovery, and personal growth.
That’s why we are dedicated to bringing you a diverse collection of
books, ranging from classic literature and specialized publications to
self-development guides and children's books.
More than just a book-buying platform, we strive to be a bridge
connecting you with timeless cultural and intellectual values. With an
elegant, user-friendly interface and a smart search system, you can
quickly find the books that best suit your interests. Additionally,
our special promotions and home delivery services help you save time
and fully enjoy the joy of reading.
Join us on a journey of knowledge exploration, passion nurturing, and
personal growth every day!
ebookbell.com

More Related Content

Similar to Advanced Swift Updated For Swift 5 Chris Eidhof (20)

PDF
The Swift Programming Language - Xcode6 for iOS App Development - AgileInfowa...
Mark Simon
 
PDF
The swift programming language
Pardeep Chaudhary
 
PDF
The Rust Programming Language 2nd Edition Steve Klabnik
onutaithakut25
 
PDF
(Ebook) The Rust Programming Language, Second Edition by Steve Klabnik, Carol...
tcgguofpg966
 
PDF
iOS 14 Programming Fundamentals with Swift Covers iOS 14 Xcode 12 and Swift 5...
zfhvtdavx3598
 
PDF
The Rust Programming Language 2nd Edition Second Converted Steve Klabnik Caro...
cizekchingbj
 
PDF
The Rust Programming Language 2nd Edition Steve Klabnik
urbuuawara
 
PDF
Programming Ios 5 2nd Edition 2nd Early Release Draft Matt Neuburg
lindzpeccoo
 
PDF
Think sharp, write swift
Pascal Batty
 
PDF
The Rust Programming Language Second Edition 2 Converted Steve Klabnik
nuovochady2s
 
PDF
Objective-C to Swift - Swift Cloud Workshop 3
Randy Scovil
 
PDF
Download Complete The Rust Programming Language 2nd Edition Steve Klabnik PDF...
maggannawsad
 
PDF
Download Full iOS 14 Programming Fundamentals with Swift Covers iOS 14 Xcode ...
vignelordi07
 
PDF
The Rust Programming Language Steve Klabnik
nmiriorola
 
PDF
Workshop Swift
Commit University
 
PDF
The Rust Programming Language Steve Klabnik
willynnekane42
 
PDF
Programming with Objective-C
Nagendra Ram
 
PDF
Programming Ios 4 Fundamentals Of Iphone Ipad And Ipod Touch Development 1st ...
jungieaugi
 
PPTX
SWIFT 3
Chuong Huynh
 
PPT
Developing iOS apps with Swift
New Generation Applications
 
The Swift Programming Language - Xcode6 for iOS App Development - AgileInfowa...
Mark Simon
 
The swift programming language
Pardeep Chaudhary
 
The Rust Programming Language 2nd Edition Steve Klabnik
onutaithakut25
 
(Ebook) The Rust Programming Language, Second Edition by Steve Klabnik, Carol...
tcgguofpg966
 
iOS 14 Programming Fundamentals with Swift Covers iOS 14 Xcode 12 and Swift 5...
zfhvtdavx3598
 
The Rust Programming Language 2nd Edition Second Converted Steve Klabnik Caro...
cizekchingbj
 
The Rust Programming Language 2nd Edition Steve Klabnik
urbuuawara
 
Programming Ios 5 2nd Edition 2nd Early Release Draft Matt Neuburg
lindzpeccoo
 
Think sharp, write swift
Pascal Batty
 
The Rust Programming Language Second Edition 2 Converted Steve Klabnik
nuovochady2s
 
Objective-C to Swift - Swift Cloud Workshop 3
Randy Scovil
 
Download Complete The Rust Programming Language 2nd Edition Steve Klabnik PDF...
maggannawsad
 
Download Full iOS 14 Programming Fundamentals with Swift Covers iOS 14 Xcode ...
vignelordi07
 
The Rust Programming Language Steve Klabnik
nmiriorola
 
Workshop Swift
Commit University
 
The Rust Programming Language Steve Klabnik
willynnekane42
 
Programming with Objective-C
Nagendra Ram
 
Programming Ios 4 Fundamentals Of Iphone Ipad And Ipod Touch Development 1st ...
jungieaugi
 
SWIFT 3
Chuong Huynh
 
Developing iOS apps with Swift
New Generation Applications
 

Recently uploaded (20)

PDF
The Different Types of Non-Experimental Research
Thelma Villaflores
 
PDF
The Constitution Review Committee (CRC) has released an updated schedule for ...
nservice241
 
PPTX
SPINA BIFIDA: NURSING MANAGEMENT .pptx
PRADEEP ABOTHU
 
PPTX
Unit 2 COMMERCIAL BANKING, Corporate banking.pptx
AnubalaSuresh1
 
PDF
SSHS-2025-PKLP_Quarter-1-Dr.-Kerby-Alvarez.pdf
AishahSangcopan1
 
PDF
People & Earth's Ecosystem -Lesson 2: People & Population
marvinnbustamante1
 
PDF
DIGESTION OF CARBOHYDRATES,PROTEINS,LIPIDS
raviralanaresh2
 
PDF
ARAL-Orientation_Morning-Session_Day-11.pdf
JoelVilloso1
 
PDF
Chapter-V-DED-Entrepreneurship: Institutions Facilitating Entrepreneurship
Dayanand Huded
 
PPTX
THE TAME BIRD AND THE FREE BIRD.pptxxxxx
MarcChristianNicolas
 
PPTX
How to Set Maximum Difference Odoo 18 POS
Celine George
 
PPT
Talk on Critical Theory, Part One, Philosophy of Social Sciences
Soraj Hongladarom
 
PPTX
Cultivation practice of Litchi in Nepal.pptx
UmeshTimilsina1
 
PDF
0725.WHITEPAPER-UNIQUEWAYSOFPROTOTYPINGANDUXNOW.pdf
Thomas GIRARD, MA, CDP
 
PDF
ARAL_Orientation_Day-2-Sessions_ARAL-Readung ARAL-Mathematics ARAL-Sciencev2.pdf
JoelVilloso1
 
PPTX
MENINGITIS: NURSING MANAGEMENT, BACTERIAL MENINGITIS, VIRAL MENINGITIS.pptx
PRADEEP ABOTHU
 
PPTX
2025 Winter SWAYAM NPTEL & A Student.pptx
Utsav Yagnik
 
PPTX
A PPT on Alfred Lord Tennyson's Ulysses.
Beena E S
 
PPTX
ASRB NET 2023 PREVIOUS YEAR QUESTION PAPER GENETICS AND PLANT BREEDING BY SAT...
Krashi Coaching
 
PPTX
How to Manage Large Scrollbar in Odoo 18 POS
Celine George
 
The Different Types of Non-Experimental Research
Thelma Villaflores
 
The Constitution Review Committee (CRC) has released an updated schedule for ...
nservice241
 
SPINA BIFIDA: NURSING MANAGEMENT .pptx
PRADEEP ABOTHU
 
Unit 2 COMMERCIAL BANKING, Corporate banking.pptx
AnubalaSuresh1
 
SSHS-2025-PKLP_Quarter-1-Dr.-Kerby-Alvarez.pdf
AishahSangcopan1
 
People & Earth's Ecosystem -Lesson 2: People & Population
marvinnbustamante1
 
DIGESTION OF CARBOHYDRATES,PROTEINS,LIPIDS
raviralanaresh2
 
ARAL-Orientation_Morning-Session_Day-11.pdf
JoelVilloso1
 
Chapter-V-DED-Entrepreneurship: Institutions Facilitating Entrepreneurship
Dayanand Huded
 
THE TAME BIRD AND THE FREE BIRD.pptxxxxx
MarcChristianNicolas
 
How to Set Maximum Difference Odoo 18 POS
Celine George
 
Talk on Critical Theory, Part One, Philosophy of Social Sciences
Soraj Hongladarom
 
Cultivation practice of Litchi in Nepal.pptx
UmeshTimilsina1
 
0725.WHITEPAPER-UNIQUEWAYSOFPROTOTYPINGANDUXNOW.pdf
Thomas GIRARD, MA, CDP
 
ARAL_Orientation_Day-2-Sessions_ARAL-Readung ARAL-Mathematics ARAL-Sciencev2.pdf
JoelVilloso1
 
MENINGITIS: NURSING MANAGEMENT, BACTERIAL MENINGITIS, VIRAL MENINGITIS.pptx
PRADEEP ABOTHU
 
2025 Winter SWAYAM NPTEL & A Student.pptx
Utsav Yagnik
 
A PPT on Alfred Lord Tennyson's Ulysses.
Beena E S
 
ASRB NET 2023 PREVIOUS YEAR QUESTION PAPER GENETICS AND PLANT BREEDING BY SAT...
Krashi Coaching
 
How to Manage Large Scrollbar in Odoo 18 POS
Celine George
 
Ad

Advanced Swift Updated For Swift 5 Chris Eidhof

  • 1. Advanced Swift Updated For Swift 5 Chris Eidhof download https://ebookbell.com/product/advanced-swift-updated-for- swift-5-chris-eidhof-10575060 Explore and download more ebooks at ebookbell.com
  • 2. Here are some recommended products that we believe you will be interested in. You can click the link to download. Advanced Swift Chris Eidhof Ole Begemann Florian Kugler Ben Cohen https://ebookbell.com/product/advanced-swift-chris-eidhof-ole- begemann-florian-kugler-ben-cohen-44569554 Advanced Swift 50 Chris Eidhof Ole Begemann Florian Kugler Ben Cohen https://ebookbell.com/product/advanced-swift-50-chris-eidhof-ole- begemann-florian-kugler-ben-cohen-44615496 Advanced Swift Objcio 3rd Edition Chris Eidhof Ole Begemann https://ebookbell.com/product/advanced-swift-objcio-3rd-edition-chris- eidhof-ole-begemann-7371436 Advanced Swift Chris Eidhofole Begemannairspeed Velocity https://ebookbell.com/product/advanced-swift-chris-eidhofole- begemannairspeed-velocity-11700822
  • 3. Advanced Ios App Architecture Realworld App Architecture In Swift 2nd Edition Ren Cacheaux https://ebookbell.com/product/advanced-ios-app-architecture-realworld- app-architecture-in-swift-2nd-edition-ren-cacheaux-38535306 Advanced Ios App Architecture Realworld App Architecture In Swift Raywenderlich Tutorial Team https://ebookbell.com/product/advanced-ios-app-architecture-realworld- app-architecture-in-swift-raywenderlich-tutorial-team-11201840 Mastering Swift 2 Dive Into The Latest Release Of The Swift Programming Language With This Advanced Apple Development Book For Creating Exceptional Ios And Osx Applications Jon Hoffman https://ebookbell.com/product/mastering-swift-2-dive-into-the-latest- release-of-the-swift-programming-language-with-this-advanced-apple- development-book-for-creating-exceptional-ios-and-osx-applications- jon-hoffman-5470890 Subsecond Annealing Of Advanced Materials Annealing By Lasers Flash Lamps And Swift Heavy Ions 1st Edition Matthias Voelskow https://ebookbell.com/product/subsecond-annealing-of-advanced- materials-annealing-by-lasers-flash-lamps-and-swift-heavy-ions-1st- edition-matthias-voelskow-4601894 Culture Shift In Advanced Industrial Society Ronald Inglehart https://ebookbell.com/product/culture-shift-in-advanced-industrial- society-ronald-inglehart-51954864
  • 6. Version 4.0 (May 2019) © 2019 Kugler und Eidhof GbR All Rights Reserved For more books, articles, and videos visit us at https://www.objc.io. Email: [email protected] Twitter: @objcio
  • 7. 1 Introduction 10 Who Is This Book For? 12 Themes 13 Terminology 16 Swift Style Guide 20 Revision History 22 2 Built-In Collections 24 Arrays 25 Arrays and Mutability 25 Array Indexing 27 Transforming Arrays 29 Array Slices 41 Dictionaries 43 Mutating Dictionaries 44 Some Useful Dictionary Methods 44 Hashable Requirement 46 Sets 47 Set Algebra 48 Index Sets and Character Sets 49 Using Sets Inside Closures 50 Ranges 51 Countable Ranges 52 Partial Ranges 53 Range Expressions 53 Recap 54 3 Optionals 56 Sentinel Values 57 Replacing Sentinel Values with Enums 59 A Tour of Optional Techniques 61 if let 61 while let 62 Doubly Nested Optionals 64 if var and while var 65 Scoping of Unwrapped Optionals 66 Optional Chaining 70
  • 8. The nil-Coalescing Operator 73 Using Optionals with String Interpolation 75 Optional map 77 Optional atMap 79 Filtering Out nils with compactMap 80 Equating Optionals 81 Comparing Optionals 84 When to Force-Unwrap 84 Improving Force-Unwrap Error Messages 86 Asserting in Debug Builds 87 Implicitly Unwrapped Optionals 89 Implicit Optional Behavior 90 Recap 90 4 Functions 91 Overview 92 Flexibility through Functions 99 Functions as Data 103 Functions as Delegates 110 Delegates, Cocoa Style 110 Delegates That Work with Structs 111 Functions Instead of Delegates 113 inout Parameters and Mutating Methods 116 Nested Functions and inout 119 When & Doesn’t Mean inout 119 Properties 120 Change Observers 121 Lazy Stored Properties 123 Subscripts 125 Custom Subscripts 126 Advanced Subscripts 126 Key Paths 128 Key Paths Can Be Modeled with Functions 130 Writable Key Paths 131 The Key Path Hierarchy 134 Key Paths Compared to Objective-C 135 Future Directions 135 Autoclosures 135 The @escaping Annotation 138 withoutActuallyEscaping 140
  • 9. Recap 141 5 Structs and Classes 142 Value Types and Reference Types 143 Mutation 147 Mutating Methods 151 inout Parameters 152 Lifecycle 153 Reference Cycles 153 Closures and Reference Cycles 158 Choosing between Unowned and Weak References 160 Deciding between Structs and Classes 161 Classes with Value Semantics 162 Structs with Reference Semantics 163 Copy-On-Write Optimization 165 Copy-On-Write Tradeoffs 166 Implementing Copy-On-Write 167 Recap 171 6 Enums 173 Overview 174 Enums Are Value Types 175 Sum Types and Product Types 177 Pattern Matching 179 Pattern Matching in Other Contexts 183 Designing with Enums 185 Switch Exhaustively 186 Make Illegal States Impossible 187 Use Enums for Modeling State 191 Choosing between Enums and Structs 195 Parallels between Enums and Protocols 197 Use Enums to Model Recursive Data Structures 200 Raw Values 206 The RawRepresentable Protocol 207 Manual RawRepresentable Conformance 208 RawRepresentable for Structs and Classes 209 Internal Representation of Raw Values 210 Enumerating Enum Cases 211
  • 10. Manual CaseIterable Conformance 212 Frozen and Non-Frozen Enums 213 Tips and Tricks 215 Recap 220 7 Strings 221 Unicode 222 Grapheme Clusters and Canonical Equivalence 224 Combining Marks 224 Emoji 227 Strings and Collections 230 Bidirectional, Not Random Access 231 Range-Replaceable, Not Mutable 232 String Indices 233 Substrings 237 StringProtocol 239 Code Unit Views 242 Index Sharing 244 Strings and Foundation 245 Other String-Related Foundation APIs 247 Ranges of Characters 249 CharacterSet 250 Unicode Properties 251 Internal Structure of String and Character 252 String Literals 254 String Interpolation 255 Custom String Descriptions 258 Text Output Streams 259 Recap 263 8 Generics 265 Generic Types 266 Extending Generic Types 268 Generics vs. Any 270 Designing with Generics 272 Recap 275
  • 11. 9 Protocols 276 Protocol Witnesses 278 Conditional Conformance 280 Protocol Inheritance 281 Designing with Protocols 282 Protocol Extensions 283 Customizing Protocol Extensions 284 Protocol Composition 287 Protocol Inheritance 288 Protocols with Associated Types 288 Conditional Conformance with Associated Types 290 Existentials 292 Existentials and Associated Types 293 Type Erasers 294 Retroactive Conformance 296 Recap 297 10 Collection Protocols 298 Sequences 300 Iterators 301 Conforming to Sequence 304 Iterators and Value Semantics 305 Function-Based Iterators and Sequences 307 Single-Pass Sequences 308 The Relationship between Sequences and Iterators 310 Conforming List to Sequence 311 Collections 313 A Custom Collection 314 Array Literals 320 Associated Types 321 Indices 322 Index Invalidation 324 Advancing Indices 325 Custom Collection Indices 326 Subsequences 329 Slices 331 Subsequences Share Indices with the Base Collection 333 Specialized Collections 334
  • 12. BidirectionalCollection 335 RandomAccessCollection 336 MutableCollection 337 RangeReplaceableCollection 339 Lazy Sequences 341 Lazy Processing of Collections 343 Recap 344 11 Error Handling 345 Error Categories 346 The Result Type 348 Throwing and Catching 350 Typed and Untyped Errors 352 Non-Ignorable Errors 354 Error Conversions 356 Converting between throws and Optionals 356 Converting between throws and Result 357 Chaining Errors 358 Chaining throws 359 Chaining Result 359 Errors in Asynchronous Code 361 Cleaning Up Using defer 364 Rethrowing 365 Bridging Errors to Objective-C 367 Recap 369 12 Encoding and Decoding 371 A Minimal Example 373 Automatic Conformance 373 Encoding 374 Decoding 376 The Encoding Process 376 Containers 377 How a Value Encodes Itself 380 The Synthesized Code 380 Coding Keys 380 The encode(to:) Method 381 The init(from:) Initializer 382
  • 13. Manual Conformance 382 Custom Coding Keys 383 Custom encode(to:) and init(from:) Implementations 384 Common Coding Tasks 386 Making Types You Don’t Own Codable 387 Making Classes Codable 390 Making Enums Codable 396 Decoding Polymorphic Collections 398 Recap 399 13 Interoperability 401 Wrapping a C Library 402 Package Manager Setup 402 Wrapping the CommonMark Library 405 A Safer Interface 411 An Overview of Low-Level Types 418 Pointers 419 Closures as C Callbacks 422 Making It Generic 424 Recap 427 14 Final Words 429
  • 15. Advanced Swift is quite a bold title for a book, so perhaps we should start with what we mean by it. When we began writing the first edition of this book, Swift was barely a year old. We did so before the beta of 2.0 was released — albeit tentatively, because we suspected the language would continue to evolve as it entered its second year. Few languages — perhaps no other language — have been adopted so rapidly by so many developers. But that left people with unanswered questions. How do you write “idiomatic” Swift? Is there a correct way to do certain things? The standard library provided some clues, but even that has changed over time, dropping some conventions and adopting others. Since its introduction nearly five years ago, Swift has evolved at a high pace, and it has become clearer what idiomatic Swift is. To someone coming from another language, Swift can resemble everything they like about their language of choice. Low-level bit twiddling can look very similar to (and can be as performant as) C, but without many of the undefined behavior gotchas. The lightweight trailing closure syntax of map or lter will be familiar to Rubyists. Swift generics are similar to C++ templates, but with type constraints to ensure generic functions are correct at the time of definition rather than at the time of use. The flexibility of higher-order functions and operator overloading means you can write code that’s similar in style to Haskell or F#. And the @objc and dynamic keywords allow you to use selectors and runtime dynamism in ways you would in Objective-C. Given these resemblances, it’s tempting to adopt the idioms of other languages. Case in point: Objective-C example projects can be almost mechanically ported to Swift. The same is true for Java or C# design patterns and most functional programming patterns. But then comes the frustration. Why can’t we use protocol extensions with associated types like interfaces in Java? Why are arrays not covariant in the way we expect? Why can’t we write “functor?” Sometimes the answer is because the part of Swift in question isn’t yet implemented. But more often, it’s either because there’s a different Swift-like way to do what you want to do, or because the Swift feature you thought was like the equivalent in some other language is, in reality, not quite what you think. Swift is a complex language — most programming languages are. But it hides that complexity well. You can get up and running developing apps in Swift without needing to know about generics or overloading or the difference between static and dynamic dispatch. You can certainly use Swift without ever calling into a C library or writing your own collection type, but after a while, we think you’ll find it necessary to know about
  • 16. these things — whether to improve your code’s performance, or to make it more elegant or expressive, or just to get certain things done. Learning more about these features is what this book is about. We intend to answer many of the “How do I do this?” or “Why does Swift behave like that?” questions we’ve seen come up again and again on various forums. Hopefully, once you’ve read our book, you’ll have gone from being aware of the basics of the language to knowing about many advanced features and having a much better understanding of how Swift works. Being familiar with the material presented is probably necessary, if not sufficient, for calling yourself an advanced Swift programmer. Who Is This Book For? This book targets experienced (though not necessarily expert) programmers, such as existing Apple-platform developers. It’s also for those coming from other languages such as Java or C++ who want to bring their knowledge of Swift to the same level as that of their “go-to” language. Additionally, it’s suitable for new programmers who started on Swift, have grown familiar with the basics, and are looking to take things to the next level. The book isn’t meant to be an introduction to Swift; it assumes you’re familiar with the syntax and structure of the language. If you want some good, compact coverage of the basics of Swift, the best source is the official Apple Swift book (available on iBooks or on Apple’s website). If you’re already a confident programmer, you could try reading our book and the Apple Swift book in parallel. This is also not a book about programming for macOS or iOS devices. Of course, since Swift is used a lot for development on Apple platforms, we’ve tried to include examples of practical use, but we hope this book will be useful for non-Apple-platform programmers as well. The vast majority of the examples in the book should run unchanged on other operating systems. The ones that don’t are either fundamentally tied to Apple’s platforms (because they use iOS frameworks or rely on the Objective-C runtime) or only require minimal changes. We can say from personal experience that Swift is a great language for writing server apps running on Linux, and the ecosystem and community have evolved over the past few years to make this a viable option.
  • 17. Themes This book is organized in such a way that each chapter covers one specific concept. There are in-depth chapters on some fundamental basic concepts like optionals and strings, along with some deeper dives into topics like C interoperability. But throughout the book, hopefully a few themes regarding Swift emerge: Swift bridges multiple levels of abstraction. Swift is a high-level language — it allows you to write code similarly to Ruby and Python, with map and reduce, and to write your own higher-order functions easily. Swift also allows you to write fast code that compiles directly to native binaries with performance similar to code written in C. What’s exciting to us, and what’s possibly the aspect of Swift we most admire, is that you’re able to do both these things at the same time. Mapping a closure expression over an array compiles to the same assembly code as looping over a contiguous block of memory does. However, there are some things you need to know about to make the most of this feature. For example, it will benefit you to have a strong grasp on how structs and classes differ, or an understanding of the difference between dynamic and static method dispatch (we’ll cover topics such as these in more depth later on). And if you ever need to drop to a lower level of abstraction and manipulate pointers directly, Swift lets you to do this as well. Swift is a multi-paradigm language. You can use it to write object-oriented code or pure functional code using immutable values, or you can write imperative C-like code using pointer arithmetic. This is both a blessing and a curse. It’s great in that you have a lot of tools available to you, and you aren’t forced into writing code one way. But it also exposes you to the risk of writing Java or C or Objective-C in Swift. Swift still has access to most of the capabilities of Objective-C, including message sending, runtime type identification, and key-value observation. But Swift introduces many capabilities not available in Objective-C. Erik Meijer, a well-known programming language expert, tweeted the following in October 2015:
  • 18. At this point, @SwiftLang is probably a better, and more valuable, vehicle for learning functional programming than Haskell. Swift is a good introduction to a more functional style of programming through its use of generics, protocols, value types, and closures. It’s even possible to use it to write operators that compose functions together. That said, most people in the Swift community seem to prefer a more imperative style while incorporating patterns that originated in functional programming. Swift’s notion of mutability for value types, as well as its error handling model, are examples of the language “hiding” functional concepts behind a friendly imperative syntax. Swift is very flexible. In the introduction to the book On Lisp, Paul Graham writes that: Experienced Lisp programmers divide up their programs differently. As well as top-down design, they follow a principle which could be called bottom-up design—changing the language to suit the problem. In Lisp, you don’t just write your program down toward the language, you also build the language up toward your program. As you’re writing a program you may think “I wish Lisp had such-and-such an operator.” So you go and write it. Afterward you realize that using the new operator would simplify the design of another part of the program, and so on. Language and program evolve together. Swift is very different from Lisp. But still, we feel like Swift also has this characteristic of encouraging “bottom-up” programming — of making it easy to write very general reusable building blocks that you then combine into larger features, which you then use to solve your actual problem. Swift is particularly good at making these building blocks feel like primitives — like part of the language. A good demonstration of this is that the many features you might think of as fundamental building blocks, like optionals or basic operators, are actually defined in a library — the Swift standard library — rather than directly in the language. Trailing closures enable you to extend the language with features that feel like they’re built in. Swift code can be compact and concise while still being clear. Swift lends itself to relatively terse code. There’s an underlying goal here, and it isn’t to save on typing. The idea is to get to the point quicker and to make code readable by dropping a lot of the “ceremonial” boilerplate you often see in other languages that obscures rather than clarifies the meaning of the code.
  • 19. For example, type inference removes the clutter of type declarations that are obvious from the context. Semicolons and parentheses that add little or no value are gone. Generics and protocol extensions encourage you to avoid repeating yourself by packaging common operations into reusable functions. The goal is to write code that’s readable at a glance. At first, this can be off-putting. If you’ve never before used functions like map, lter, and reduce, they might come across as more difficult to read than a simple for loop. But our hope is that this is a short learning curve and that the reward is code that is more “obviously correct” at first glance. Swift tries to be as safe as is practical, until you tell it not to be. This is unlike languages such as C and C++ (where you can be unsafe easily just by forgetting to do something), or like Haskell or Java (which are sometimes safe whether or not you like it). Eric Lippert, one of the principal designers of C#, wrote about his 10 regrets of C#, including the lesson that: sometimes you need to implement features that are only for experts who are building infrastructure; those features should be clearly marked as dangerous—not invitingly similar to features from other languages. Eric was specifically referring to C#’s finalizers, which are similar to C++ destructors. But unlike destructors, they run at a nondeterministic time (perhaps never) at the behest of the garbage collector (and on the garbage collector’s thread). However, Swift, being reference counted, does execute a class’s deinit deterministically. Swift embodies this sentiment in other ways. Undefined and unsafe behavior is avoided by default. For example, a variable can’t be used until it’s been initialized, and using out-of-bounds subscripts on an array will trap, as opposed to continuing with possibly garbage values. There are a number of “unsafe” options available (such as the unsafeBitCast function, or the UnsafeMutablePointer type) for when you really need them. But with great power comes great undefined behavior. For example, you can write the following:
  • 20. var someArray = [1, 2, 3] let uhOh = someArray.withUnsafeBufferPointer { ptr in return ptr } // Later... print(uhOh[10]) It’ll compile, but who knows what it’ll do. The ptr variable is only valid within the closure expression, and returning it to the caller is illegal. But there is nothing stopping you from letting it escape into the wild. However, you can’t say nobody warned you. Swift is an opinionated language. We as authors have strong opinions about the “right” way to write Swift. You’ll see many of them in this book, sometimes expressed as if they’re facts. But they’re just our opinions — feel free to disagree! Swift is still a young language, and many things aren’t settled. Regardless of what you’re reading, the most important thing is to try things out for yourself, check how they behave, and decide how you feel about them. Think critically, and beware of out-of-date information. Swift continues to evolve. The period of major yearly syntax changes is behind us, but important areas of the language are still unfinished (string APIs, the generics system), in flux (reflection), or haven’t been tackled yet (concurrency). Terminology ‘When I use a word,’ Humpty Dumpty said, in rather a scornful tone, ‘it means just what I choose it to mean — neither more nor less.’ — Through the Looking Glass, by Lewis Carroll Programmers throw around terms of art a lot. To avoid confusion, what follows are some definitions of terms we use throughout this book. Where possible, we’re trying to adhere to the same usage as the official documentation, or sometimes a definition that’s been widely adopted by the Swift community. Many of these definitions are covered in more detail in later chapters, so don’t worry if not everything makes sense right away. If you’re already familiar with all of these terms, it’s still best to skim through to make sure your accepted meanings don’t differ from ours. In Swift, we make the distinction between values, variables, references, and constants.
  • 21. A value is immutable and forever — it never changes. For example, 1, true, and [1,2,3] are all values. These are examples of literals, but values can also be generated at runtime. The number you get when you square the number five is a value. When we assign a value to a name using var x = [1,2], we’re creating a variable named x that holds the value [1,2]. By changing x, e.g. by performing x.append(3), we didn’t change the original value. Rather, we replaced the value that x holds with the new value, [1,2,3] — at least logically, if not in the actual implementation (which might actually just tack a new entry on the back of some existing memory). We refer to this as mutating the variable. We can declare constant variables (constants, for short) with let instead of var. Once a constant has been assigned a value, it can never be assigned a new value. We also don’t need to give a variable a value immediately. We can declare the variable first (let x: Int) and then later assign a value to it (x = 1). Swift, with its emphasis on safety, will check that all possible code paths lead to a variable being assigned a value before its value can be read. There’s no concept of a variable having an as-yet-undefined value. Of course, if the variable was declared with let, it can only be assigned to once. Structs and enums are value types. When you assign one struct variable to another, the two variables will then contain the same value. You can think of the contents as being copied, but it’s more accurate to say that one variable was changed to contain the same value as the other. A reference is a special kind of value: it’s a value that “points to” some other location in memory. Because two references can refer to the same location, this introduces the possibility of the value stored at that location getting mutated by two different parts of the program at once. Classes are reference types. You can’t hold an instance of a class (which we might occasionally call an object — a term fraught with troublesome overloading!) directly in a variable. Instead, you must hold a reference to it in a variable and access it via that reference. Reference types have identity — you can check if two variables are referring to the exact same object by using ===. You can also check if they’re equal, assuming == is implemented for the relevant type. Two objects with different identities can still be equal.
  • 22. Value types don’t have identity. You can’t check if a particular variable holds the “same” number 2 as another. You can only check if they both contain the value 2. === is really asking: “Do both these variables hold the same reference as their value?” In programming language literature, == is sometimes called structural equality, and === is called pointer equality or reference equality. Class references aren’t the only kind of reference in Swift. For example, there are also pointers, accessed through withUnsafeMutablePointer functions and the like. But classes are the simplest reference type to use, in part because their reference-like nature is partially hidden from you by syntactic sugar, meaning you don’t need to do any explicit “dereferencing” like you do with pointers in some other languages. (We’ll cover the other kind of references in more detail in the Interoperability chapter.) A variable that holds a reference can be declared with let — that is, the reference is constant. This means that the variable can never be changed to refer to something else. But — and this is important — it doesn’t mean that the object it refers to can’t be changed. So when referring to a variable as a constant, be careful — it’s only constant in what it points to. It doesn’t mean what it points to is constant. (Note: If those last few sentences sound like doublespeak, don’t worry, as we cover this again in the Structs and Classes chapter.) Unfortunately, this means that when looking at a declaration of a variable with let, you can’t tell at a glance whether or not what’s being declared is completely immutable. Instead, you have to know whether it’s holding a value type or a reference type. When a value type is copied, it generally performs a deep copy, i.e. all values it contains are also copied recursively. This copy can occur eagerly (whenever a new variable is introduced) or lazily (whenever a variable gets mutated). Types that perform deep copies are said to have value semantics. Here we hit another complication. If a struct contains reference types, the referenced objects won’t automatically get copied upon assigning the struct to a new variable. Instead, only the references themselves get copied. These are called shallow copies. For example, the Data struct in Foundation is a wrapper around a class that stores the actual bytes. However, the authors of the Data struct took extra steps to also perform a deep copy of the class instance whenever the Data struct is mutated. They do this efficiently using a technique called copy-on-write, which we’ll explain in the Structs and Classes chapter. For now, it’s important to know that this behavior doesn’t come for free. The collections in the standard library also wrap reference types and use copy-on-write to efficiently provide value semantics. However, if the elements in a collection are
  • 23. references (for example, an array containing objects), the objects won’t get copied. Instead, only the references get copied. This means that a Swift array only has value semantics if its elements have value semantics too. Some classes are completely immutable — that is, they provide no methods for changing their internal state after they’re created. This means that even though they’re classes, they also have value semantics (because even if they’re shared, they can never change). Be careful though — only nal classes can be guaranteed not to be subclassed with added mutable state. In Swift, functions are also values. You can assign a function to a variable, have an array of functions, and call the function held in a variable. Functions that take other functions as arguments (such as map, which takes a function to transform every element of a sequence) or return functions are referred to as higher-order functions. Functions don’t have to be declared at the top level — you can declare a function within another function or in a do or other scope. Functions defined within an outer scope but passed out from it (say, as the returned value of a function), can “capture” local variables, in which case those local variables aren’t destroyed when the local scope ends, and the function can hold state through them. This behavior is called “closing over” variables, and functions that do this are called closures. Functions can be declared either with the func keyword or by using a shorthand { } syntax called a closure expression. Sometimes this gets shortened to “closures,” but don’t let it give you the impression that only closure expressions can be closures. Functions declared with the func keyword are also closures when they close over external variables. Functions are held by reference. This means assigning a function that has captured state to another variable doesn’t copy that state; it shares it, similar to object references. What’s more is that when two closures close over the same local variable, they both share that variable, so they share state. This can be quite surprising, and we’ll discuss this more in the Functions chapter. Functions defined inside a class or protocol are methods, and they have an implicit self parameter. Sometimes we call functions that aren’t methods free functions. This is to distinguish them from methods. A fully qualified function name in Swift includes not just the function’s base name (the part before the parentheses), but also the argument labels. For example, the full name of the method for moving a collection index by a number of steps is index(_:offsetBy:),
  • 24. indicating that this function takes two arguments (represented by the two colons), the first one of which has no label (represented by the underscore). We often omit the labels in the book if it’s clear from the context what function we’re referring to; the compiler allows you to do the same. Free functions, and methods called on structs, are statically dispatched. This means the function that’ll be called is known at compile time. It also means the compiler might be able to inline the function, i.e. not call the function at all, but instead replace it with the code the function would execute. The optimizer can also discard or simplify code that it can prove at compile time won’t actually run. Methods on classes or protocols might be dynamically dispatched. This means the compiler doesn’t necessarily know at compile time which function will run. This dynamic behavior is done either by using vtables (similar to how Java and C++ dynamic dispatch work), or in the case of some @objc classes and protocols, by using selectors and objc_msgSend. Subtyping and method overriding is one way of getting polymorphic behavior, i.e. behavior that varies depending on the types involved. A second way is function overloading, where a function is written multiple times for different types. (It’s important not to mix up overriding and overloading, as they behave very differently.) A third way is via generics, where a function or method is written once to take any type that provides certain functions or methods, but the implementations of those functions can vary. Unlike method overriding, the results of function overloading and generics are known statically at compile time. We’ll cover this more in the Generics chapter. Swift Style Guide When writing this book, and when writing Swift code for our own projects, we try to stick to the following rules: → For naming, clarity at the point of use is the most important consideration. Since APIs are used many more times than they’re declared, their names should be optimized for how well they work at the call site. Familiarize yourself with the Swift API Design Guidelines and try to adhere to them in your own code. → Clarity is often helped by conciseness, but brevity should never be a goal in and of itself. → Always add documentation comments to functions — especially generic ones.
  • 25. → Types start with UpperCaseLetters. Functions, variables, and enum cases start with lowerCaseLetters. → Use type inference. Explicit but obvious types get in the way of readability. → Don’t use type inference in cases of ambiguity or when defining contracts (which is why, for example, funcs have an explicit return type). → Default to structs unless you actually need a class-only feature or reference semantics. → Mark classes as nal unless you’ve explicitly designed them to be inheritable. If you want to use inheritance internally but not allow subclassing for external clients, mark a class public but not open. → Use the trailing closure syntax, except when that closure is immediately followed by another opening brace. → Use guard to exit functions early. → Eschew force-unwraps and implicitly unwrapped optionals. They’re occasionally useful, but needing them constantly is usually a sign something is wrong. → Don’t repeat yourself. If you find you’ve written a very similar piece of code more than a couple of times, extract it into a function. Consider making that function a protocol extension. → Favor map and lter. But don’t force it: use a for loop when it makes sense. The purpose of higher-order functions is to make code more readable. An obfuscated use of reduce when a simple for loop would be clearer defeats this purpose. → Favor immutable variables: default to let unless you know you need mutation. But use mutation when it makes the code clearer or more efficient. Again, don’t force it: a mutating method on a struct is often more idiomatic and efficient than returning a brand new struct. → Swift generics (especially in combination with protocol constraints) tend to lead to very long function signatures. Unfortunately, we have yet to settle on a good way of breaking up long function declarations into multiple lines. We’ll try to be consistent in how we do this in sample code. → Leave off self. when you don’t need it. In closure expressions, the presence of self. is a clear signal that self is being captured by the closure. → Instead of writing a free function, write an extension on a type or protocol (whenever you can). This helps with readability and discoverability.
  • 26. One final note about our code samples throughout the book: to save space and focus on the essentials, we usually omit import statements that would be required to make the code compile. If you try out the code yourself and the compiler tells you it doesn’t recognize a particular symbol, try adding an import Foundation or import UIKit statement. Revision History Fourth Edition (May 2019) → All chapters revised for Swift 5. → New chapter: Enums → Rewritten chapters: → Structs and Classes → Generics → Protocols → Significant changes and new content: → Strings → Collection Protocols → Error Handling → Reordered the chapters; Collection Protocols has been moved further back in the book, resulting in a smoother learning curve for readers. → Florian Kugler joined as a co-author. Third Edition (October 2017) → All chapters revised for Swift 4. → New chapter: Encoding and Decoding → Significant changes and new content: → Built-In Collections → Collection Protocols
  • 27. → Functions (new section on key paths) → Strings (more than 40 percent longer) → Interoperability → Full text available as Xcode playgrounds. Second Edition (September 2016) → All chapters revised for Swift 3. → Split the Collections chapter into Built-In Collections and Collection Protocols. → Significant changes and new content throughout the book, especially in: → Collection Protocols → Functions → Generics → Full text available as a Swift playground for iPad. → Ole Begemann joined as a co-author. First Edition (March 2016) → Initial release (covering Swift 2.2).
  • 29. Collections of elements are among the most important data types in any programming language. Good language support for different kinds of containers has a big impact on programmer productivity and happiness. Swift places special emphasis on sequences and collections — so much of the standard library is dedicated to this topic that we sometimes have the feeling it deals with little else. The resulting model is more extensible than what you may be used to from other languages, but it’s also quite complex. In this chapter, we’re going to take a look at the major collection types Swift ships with, with a focus on how to work with them effectively and idiomatically. In the Collection Protocols chapter later in the book, we’ll climb up the abstraction ladder and see how the collection protocols in the standard library work. Arrays Arrays and Mutability Arrays are the most common collections in Swift. An array is an ordered container of elements that all have the same type, and it provides random access to each element. As an example, to create an array of numbers, we can write the following: // The Fibonacci numbers let fibs = [0, 1, 1, 2, 3, 5] If we try to modify the array defined above (by using append(_:), for example), we get a compile error. This is because the array is defined as a constant, using let. In many cases, this is exactly the correct thing to do; it prevents us from accidentally changing the array. If we want the array to be a variable, we have to define it using var: var mutableFibs = [0, 1, 1, 2, 3, 5] Now we can easily append a single element or a sequence of elements: mutableFibs.append(8) mutableFibs.append(contentsOf: [13, 21]) mutableFibs // [0, 1, 1, 2, 3, 5, 8, 13, 21] There are a couple of benefits that come with making the distinction between var and let. Constants defined with let are easier to reason about because they’re immutable. When
  • 30. you read a declaration like let bs = ..., you know that the value of bs will never change — the immutability is enforced by the compiler. This helps greatly when reading through code. However, note that this is only true for types that have value semantics. A let variable containing a reference to a class instance guarantees that the reference will never change, i.e. you can’t assign another object to that variable. However, the object the reference points to can change. We’ll go into more detail on these differences in the chapter on Structs and Classes. Arrays, like all collection types in the standard library, have value semantics. When you assign an existing array to another variable, the array contents are copied over. For example, in the following code snippet, x is never modified: var x = [1,2,3] var y = x y.append(4) y // [1, 2, 3, 4] x // [1, 2, 3] The statement var y = x makes a copy of x, so appending 4 to y won’t change x — the value of x will still be [1, 2, 3]. The same thing happens when you pass an array into a function; the function receives a local copy of the array, and any changes it makes don’t affect the caller. Compare this with the approach to mutability taken by NSArray in Foundation. NSArray has no mutating methods — to mutate an array, you need an NSMutableArray. But just because you have a non-mutating NSArray reference does not mean the array can’t be mutated underneath you: let a = NSMutableArray(array: [1,2,3]) // I don't want to be able to mutate b. let b: NSArray = a // But it can still be mutated — via a. a.insert(4, at: 3) b // ( 1, 2, 3, 4 ) The correct way to write this is to manually create a copy upon assignment: let c = NSMutableArray(array: [1,2,3]) // I don't want to be able to mutate d. let d = c.copy() as! NSArray
  • 31. c.insert(4, at: 3) d // ( 1, 2, 3 ) In the example above, it’s very clear that we need to make a copy — a is mutable, after all. However, when passing around arrays between methods and functions, this isn’t always so easy to see. In Swift, there’s just one array type, and mutability is controlled by declaring with var instead of let. But there’s no reference sharing — when you declare a second array with let, you’re guaranteed it’ll never change. Making so many copies could be a performance problem, but in practice, all collection types in the Swift standard library are implemented using a technique called copy-on-write, which makes sure the data is only copied when necessary. So in our example, x and y shared internal storage up until the point y.append was called. In the chapter on Structs and Classes, we’ll take a deeper look at value semantics, including how to implement copy-on-write for your own types: Array Indexing Swift arrays provide all the usual operations you’d expect, such as isEmpty and count. Arrays also allow for direct access of elements at a specific index through subscripting, like with bs[3]. Keep in mind that you need to make sure the index is within bounds before getting an element via subscript. Fetch the element at index 3, and you’d better be sure the array has at least four elements in it. Otherwise, your program will trap, i.e. abort with a fatal error. Swift has many ways to work with arrays without you ever needing to calculate an index: → Want to iterate over the array? for x in array → Want to iterate over all but the first element of an array? for x in array.dropFirst() → Want to iterate over all but the last five elements? for x in array.dropLast(5) → Want to number all the elements in an array? for (num, element) in array.enumerated()
  • 32. → Want to find the location of a specific element? if let idx = array. rstIndex { someMatchingLogic($0) } → Want to transform all the elements in an array? array.map { someTransformation($0) } → Want to fetch only the elements matching a specific criterion? array. lter { someCriteria($0) } Another sign that Swift wants to discourage you from doing index math is the removal of traditional C-style for loops from the language in Swift 3. Manually fiddling with indices is a rich sea of bugs to mine, so it’s often best avoided. But sometimes you do have to use an index. And with array indices, the expectation is that when you do, you’ll have thought very carefully about the logic behind the index calculation. So to have to unwrap the value of a subscript operation is probably overkill — it means you don’t trust your code. But chances are you do trust your code, so you’ll probably resort to force-unwrapping the result, because you know the index must be valid. This is (a) annoying, and (b) a bad habit to get into. When force-unwrapping becomes routine, eventually you’re going to slip up and force-unwrap something you don’t mean to. So to avoid this habit becoming routine, arrays don’t give you the option. While a subscripting operation that responds to an invalid index with a controlled crash could arguably be called unsafe, that’s only one aspect of safety. Subscripting is totally safe in regard to memory safety — the standard library collections always perform bounds checks to prevent unauthorized memory access with an out-of-bounds index. Other operations behave differently. The rst and last properties return an optional value, which is nil if the array is empty. rst is equivalent to isEmpty ? nil : self[0]. Similarly, the removeLast method will trap if you call it on an empty array, whereas popLast will only delete and return the last element if the array isn’t empty, and otherwise it will do nothing and return nil. Which one you’d want to use depends on your use case. When you’re using the array as a stack, you’ll probably always want to combine checking for empty and removing the last entry. On the other hand, if you already know whether or not the array is empty, dealing with the optional is fiddly. We’ll encounter these tradeoffs again later in this chapter when we talk about dictionaries. Additionally, there’s an entire chapter dedicated to Optionals.
  • 33. Transforming Arrays map It’s common to need to perform a transformation on every value in an array. Every programmer has written similar code hundreds of times: create a new array, loop over all the elements in an existing array, perform an operation on an element, and append the result of that operation to the new array. For example, the following code squares an array of integers: var squared: [Int] = [] for fib in fibs { squared.append(fib * fib) } squared // [0, 1, 1, 4, 9, 25] Swift arrays have a map method, which was adopted from the world of functional programming. Here’s the exact same operation using map: let squares = fibs.map { fib in fib * fib } squares // [0, 1, 1, 4, 9, 25] This version has three main advantages. It’s shorter, of course. There’s also less room for error. But more importantly, it’s clearer: all the clutter has been removed. Once you’re used to seeing and using map everywhere, it acts as a signal — you see map, and you immediately know what’s happening: a function is going to be applied to every element, returning a new array of the transformed elements. The declaration of squared no longer needs to be made with var, because we aren’t mutating it any longer — it’ll be delivered out of the map fully formed, so we can declare squares with let, if appropriate. And because the type of the contents can be inferred from the function passed to map, squares no longer needs to be explicitly typed. The map method isn’t hard to write — it’s just a question of wrapping up the boilerplate parts of the for loop into a generic function. Here’s one possible implementation (though in Swift, it’s actually an extension of the Sequence protocol, which we’ll cover in the Collection Protocols chapter): extension Array { func map<T>(_ transform: (Element) -> T) -> [T] {
  • 34. var result: [T] = [] result.reserveCapacity(count) for x in self { result.append(transform(x)) } return result } } Element is the generic placeholder for whatever type the array contains, and T is a new placeholder that represents the result of the element transformation. The map function itself doesn’t care what Element and T are; they can be anything at all. The concrete type T of the transformed elements is defined by the return type of the transform function the caller passes to map. See the Generics chapter for details on generic parameters. Really, the signature of this method should be func map<T>(_ transform: (Element) throws -> T) rethrows -> [T], indicating that map will forward any error the transformation function might throw to the caller. We’ll cover this in detail in the Errors chapter, but here we’ve left the error handling annotations out for the sake of simplicity. If you’d like, you can check out the source code for Sequence.map in the Swift repository on GitHub. Parameterizing Behavior with Functions Even if you’re already familiar with map, take a moment and consider the map implementation. What makes it so general yet so useful? map manages to separate out the boilerplate — which doesn’t vary from call to call — from the functionality that always varies, i.e. the logic of how exactly to transform each element. It does this through a parameter the caller supplies: the transformation function. This pattern of parameterizing behavior is found throughout the standard library. For example, there are more than a dozen separate methods on Array (and on other kinds of collections) that take a function to customize their behavior: → map and atMap — transform the elements
  • 35. → lter — include only certain elements → allSatisfy — test all elements for a condition → reduce — fold the elements into an aggregate value → forEach — visit each element → sort(by:), sorted(by:), lexicographicallyPrecedes(_:by:), and partition(by:) — reorder the elements → rstIndex(where:), lastIndex(where:), rst(where:), last(where:), and contains(where:) — does an element exist? → min(by:) and max(by:) — find the minimum or maximum of all elements → elementsEqual(_:by:) and starts(with:by:) — compare the elements to another array → split(whereSeparator:) — break up the elements into multiple arrays → pre x(while:) — take elements from the start as long as the condition holds true → drop(while:) — drop elements until the condition ceases to be true, and then return the rest (similar to pre x, but this returns the inverse) → removeAll(where:) — remove the elements matching the condition The goal of all these functions is to get rid of the clutter of the uninteresting parts of the code, such as the creation of a new array and the for loop over the source data. Instead, the clutter is replaced with a single word that describes what’s being done. This brings the important code – the logic the programmer wants to express – to the forefront. Several of these functions have a default behavior. sort sorts elements in ascending order when they’re comparable, unless you specify otherwise, and contains can take a value to check for, so long as the elements are equatable. These defaults help make the code even more readable. Ascending order sorting is natural, so the meaning of array.sort() is intuitive, and array. rstIndex(of: "foo") is clearer than array. rstIndex { $0 == "foo" }. But in every instance, these are just shorthand for the common cases. Elements don’t have to be comparable or equatable, and you don’t have to compare the entire element — you can sort an array of people by their ages (people.sort { $0.age < $1.age }) or check if the array contains anyone underage (people.contains { $0.age < 18 }). You can also compare some transformation of the element. For example, an admittedly inefficient
  • 36. case- and locale-insensitive sort could be performed via people.sort { $0.name.uppercased() < $1.name.uppercased() }. There are other functions of similar usefulness that would also take a function to specify their behaviors but which aren’t in the standard library. You could easily define them yourself (and might like to try): → accumulate — combine elements into an array of running values (like reduce, but returning an array of each interim combination) → count(where:) — count the number of elements that match (this should have been part of the Swift 5.0 standard library, but got delayed due to a name clash with the count property; it will probably be reintroduced in a subsequent release though) → indices(where:) — return a list of indices matching a condition (similar to rstIndex(where:), but it doesn’t stop on the first one) If you find yourself iterating over an array to perform the same task or a similar one more than a couple of times in your code, consider writing a short extension to Array. For example, the following code splits an array into groups of adjacent equal elements: let array: [Int] = [1, 2, 2, 2, 3, 4, 4] var result: [[Int]] = array.isEmpty ? [] : [[array[0]]] for (previous, current) in zip(array, array.dropFirst()) { if previous == current { result[result.endIndex-1].append(current) } else { result.append([current]) } } result // [[1], [2, 2, 2], [3], [4, 4]] We can formalize this algorithm by abstracting the code that loops over the array in pairs of adjacent elements from the logic that varies between applications (deciding where to split the array). We use a function argument to allow the caller to customize the latter: extension Array { func split(where condition: (Element, Element) -> Bool) -> [[Element]] { var result: [[Element]] = array.isEmpty ? [] : [[self[0]]] for (previous, current) in zip(self, self.dropFirst()) { if condition(previous, current) {
  • 37. result.append([current]) } else { result[result.endIndex-1].append(current) } } return result } } This allows us to replace the for loop with the following: let parts = array.split { $0 != $1 } parts // [[1], [2, 2, 2], [3], [4, 4]] Or, in the case of this particular condition, we can even write: let parts2 = array.split(where: !=) This has all the same benefits we described for map. The example with split(where:) is more readable than the example with the for loop; even though the for loop is simple, you still have to run the loop through in your head, which is a small mental tax. Using split(where:) introduces less chance of error (for example, accidentally forgetting the case of the array being empty), and it allows you to declare the result variable with let instead of var. We’ll say more about extending collections and using functions later in the book. Mutation and Stateful Closures When iterating over an array, you could use map to perform side effects (e.g. inserting elements into some lookup table). We don’t recommend doing this. Take a look at the following: array.map { item in table.insert(item) } This hides the side effect (the mutation of the lookup table) in a construct that looks like a transformation of the array. If you ever see something like the above, then it’s a clear
  • 38. case for using a plain for loop instead of a function like map. The forEach method would also be more appropriate than map in this case, but it has its own issues, so we’ll look at forEach a bit later. Performing side effects is different than deliberately giving the closure local state, which is a particularly useful technique. In addition to being useful, it’s what makes closures — functions that can capture and mutate variables outside their scope — so powerful a tool when combined with higher-order functions. For example, the accumulate function described above could be implemented with map and a stateful closure, like this: extension Array { func accumulate<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element) -> Result) -> [Result] { var running = initialResult return map { next in running = nextPartialResult(running, next) return running } } } This creates a temporary variable to store the running value and then uses map to create an array of the running values as the computation progresses: [1,2,3,4].accumulate(0, +) // [1, 3, 6, 10] Note that this code assumes that map performs its transformation in order over the sequence. In the case of our map above, it does. But there are possible implementations that could transform the sequence out of order — for example, one that performs the transformation of the elements concurrently. The official standard library version of map doesn’t specify whether or not it transforms the sequence in order, though it seems like a safe bet that it does. lter Another very common operation is that of taking an array and creating a new array that only includes the elements that match a certain condition. The pattern of looping over an array and selecting the elements that match the given predicate is captured in the lter method:
  • 39. let nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] nums.filter { num in num % 2 == 0 } // [2, 4, 6, 8, 10] We can use Swift’s shorthand notation for arguments of a closure expression to make this even shorter. Instead of naming the num argument, we can write the above code like this: nums.filter { $0 % 2 == 0 } // [2, 4, 6, 8, 10] For very short closures, this can be more readable. If the closure is more complicated, it’s almost always a better idea to name the arguments explicitly, as we’ve done before. It’s really a matter of personal taste — choose whichever option is more readable at a glance. A good rule of thumb is this: if the closure fits neatly on one line, shorthand argument names are a good fit. By combining map and lter, we can write a lot of operations on arrays without having to introduce a single intermediate variable. The resulting code will become shorter and easier to read. For example, to find all squares under 100 that are even, we could map the range 1..<10 in order to square its members, and then we could filter out all odd numbers: (1..<10).map { $0 * $0 }.filter { $0 % 2 == 0 } // [4, 16, 36, 64] The implementation of lter looks similar to map: extension Array { func filter(_ isIncluded: (Element) -> Bool) -> [Element] { var result: [Element] = [] for x in self where isIncluded(x) { result.append(x) } return result } } One quick performance tip: if you ever find yourself writing something like the following, stop! bigArray.filter { someCondition }.count > 0
  • 40. lter creates a brand-new array and processes every element in the array. But this is unnecessary. This code only needs to check if one element matches — in which case, contains(where:) will do the job: bigArray.contains { someCondition } This is much faster for two reasons: it doesn’t create a whole new array of the filtered elements just to count them, and it exits early — as soon as it finds the first match. Generally, only ever use lter if you want all the results. reduce Both map and lter take an array and produce a new, modified array. Sometimes, however, you might want to combine all elements into a single new value. For example, to sum up all the elements, we could write the following code: let fibs = [0, 1, 1, 2, 3, 5] var total = 0 for num in fibs { total = total + num } total // 12 The reduce method takes this pattern and abstracts two parts: the initial value (in this case, zero), and the function for combining the intermediate value (total) and the element (num). Using reduce, we can write the same example like this: let sum = fibs.reduce(0) { total, num in total + num } // 12 Operators are functions too, so we could’ve also written the same example like this: fibs.reduce(0, +) // 12 The output type of reduce doesn’t have to be the same as the element type. For example, if we want to convert a list of integers into a string, with each number followed by a comma and a space, we can do the following: fibs.reduce("") { str, num in str + "(num), " } // 0, 1, 1, 2, 3, 5, Here’s the implementation for reduce:
  • 41. extension Array { func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element) -> Result) -> Result { var result = initialResult for x in self { result = nextPartialResult(result, x) } return result } } Another performance tip: reduce is very flexible, and it’s common to see it used to build arrays and perform other operations. For example, you can implement map and lter using only reduce: extension Array { func map2<T>(_ transform: (Element) -> T) -> [T] { return reduce([]) { $0 + [transform($1)] } } func filter2(_ isIncluded: (Element) -> Bool) -> [Element] { return reduce([]) { isIncluded($1) ? $0 + [$1] : $0 } } } This is kind of beautiful and has the benefit of not needing those icky imperative for loops. But Swift isn’t Haskell, and Swift arrays aren’t lists. What’s happening here is that on every execution of the combine function, a brand-new array is being created by appending the transformed or included element to the previous one. This means that both these implementations are O(n2), not O(n) — as the length of the array increases, the time these functions take increases quadratically. There’s a second version of reduce, which has a different type. More specifically, the function for combining an intermediate result and an element takes Result as an inout parameter:
  • 42. public func reduce<Result>(into initialResult: Result, _ updateAccumulatingResult: (_ partialResult: inout Result, Element) throws -> () ) rethrows -> Result We discuss inout parameters in detail in the chapter on Structs and Classes, but for now, think of the inout Result parameter as a mutable parameter: we can modify it within the function. This allows us to write lter in a much more efficient way: extension Array { func filter3(_ isIncluded: (Element) -> Bool) -> [Element] { return reduce(into: []) { result, element in if isIncluded(element) { result.append(element) } } } } When using inout, the compiler doesn’t have to create a new array each time, so this version of lter is again O(n). When the call to reduce(into:_:) is inlined by the compiler, the generated code is often the same as when using a for loop. A Flattening map Sometimes, you want to map an array where the transformation function returns another array and not a single element. For example, let’s say we have a function, extractLinks, that takes a Markdown file and returns an array containing the URLs of all the links in the file. The function signature looks like this: func extractLinks(markdownFile: String) -> [URL] If we have a bunch of Markdown files and want to extract the links from all files into a single array, we could try to write something like markdownFiles.map(extractLinks). But this returns an array of arrays containing the URLs: one array per file. Now you could just perform the map, get back an array of arrays, and then call joined to flatten the results into a single array:
  • 43. let markdownFiles: [String] = // ... let nestedLinks = markdownFiles.map(extractLinks) let links = nestedLinks.joined() The atMap method combines these two operations, mapping and flattening, into a single step. So markdownFiles. atMap(extractLinks) returns all the URLs in an array of Markdown files as a single array. The signature for atMap is almost identical to map, except its transformation function returns an array. The implementation uses append(contentsOf:) instead of append(_:) to flatten the result array: extension Array { func flatMap<T>(_ transform: (Element) -> [T]) -> [T] { var result: [T] = [] for x in self { result.append(contentsOf: transform(x)) } return result } } Another great use case for atMap is combining elements from different arrays. To get all possible pairs of the elements in two arrays, atMap over one array and then map over the other in the inner transformation function: let suits = ["♠", "♥", "♣", "♦"] let ranks = ["J", "Q", "K", "A"] let result = suits.flatMap { suit in ranks.map { rank in (suit, rank) } } /* [("♠", "J"), ("♠", "Q"), ("♠", "K"), ("♠", "A"), ("♥", "J"), ("♥", "Q"), ("♥", "K"), ("♥", "A"), ("♣", "J"), ("♣", "Q"), ("♣", "K"), ("♣", "A"), ("♦", "J"), ("♦", "Q"), ("♦", "K"), ("♦", "A")] */
  • 44. Iteration Using forEach The final operation we’d like to discuss is forEach. It works almost like a for loop: the passed-in function is executed once for each element in the sequence. And unlike map, forEach doesn’t return anything — it is specifically meant for performing side effects. Let’s start by mechanically replacing a loop with forEach: for element in [1, 2, 3] { print(element) } [1, 2, 3].forEach { element in print(element) } This isn’t a big win, but it can be handy if the action you want to perform is a single function call on each element in a collection. Passing a function name to forEach instead of passing a closure expression can lead to clearer and more concise code. For example, if you’re writing a view controller on iOS and want to add an array of subviews to the main view, you can just use theViews.forEach(view.addSubview). However, there are some subtle differences between for loops and forEach. For instance, if a for loop has a return statement in it, rewriting it with forEach can significantly change the code’s behavior. Consider the following example, which is written using a for loop with a where condition: extension Array where Element: Equatable { func firstIndex(of element: Element) -> Int? { for idx in self.indices where self[idx] == element { return idx } return nil } } We can’t directly replicate the where clause in the forEach construct, so we might (incorrectly) rewrite this using lter: extension Array where Element: Equatable { func firstIndex_foreach(of element: Element) -> Int? { self.indices.filter { idx in
  • 45. self[idx] == element }.forEach { idx in return idx } return nil } } The return inside the forEach closure doesn’t return out of the outer function; it only returns from the closure itself. In this particular case, we’d probably have found the bug, because the compiler generates a warning that the argument to the return statement is unused, but you shouldn’t rely on it finding every such issue. Also, consider the following example: (1..<10).forEach { number in print(number) if number > 2 { return } } It’s not immediately obvious that this prints out all the numbers in the input range. The return statement isn’t breaking the loop; rather, it’s returning from the closure, thus starting a new iteration of the loop inside forEachs’s implementation. In some situations, such as the addSubview example above, forEach can be nicer than a for loop. However, because of the non-obvious behavior of return, we recommend against most other uses of forEach. Just use a regular for loop instead. Array Slices In addition to accessing a single element of an array by subscript (e.g. bs[0]), we can also retrieve a range of elements by subscript. For example, to get all but the first element of an array, we can do the following: let slice = fibs[1...] slice // [1, 1, 2, 3, 5] type(of: slice) // ArraySlice<Int>
  • 46. This gets us a slice of the array starting at the second element. The type of the result is ArraySlice, not Array. ArraySlice is a view on arrays. It’s backed by the original array, yet it provides a view on just the slice. As a result, creating a slice is cheap — the array elements don’t get copied. length: Int 6 storage: Pointer ptr 0 storage: Pointer startIndex: Int ptr 1 endIndex: Int 6 1 1 2 3 Unused reserved capacity Contents of !bs… … shares the same storage as slice 5 Figure 2.1: Array Slices The ArraySlice type has the same methods defined as Array does (because both conform to the same protocols, most importantly Collection), so you can use a slice as if it were an array. If you do need to convert a slice into an array, you can just construct a new array out of the slice: let newArray = Array(slice) type(of: newArray) // Array<Int> It’s important to keep in mind that slices use the same index as their base collection does to refer to a particular element. As a consequence, slice indices don’t necessarily start at zero. For example, the first element of the bs[1...] slice we created above is at index 1, and accessing slice[0] by mistake would crash our program with an out-of-bounds violation. If you work with indices, we recommend you always base your calculations on the startIndex and endIndex properties, even if you’re dealing with a
  • 47. plain array where 0 and count-1 would also do the trick. It’s just too easy for this implicit assumption to break later on. Dictionaries Another key data structure is Dictionary. A dictionary contains unique keys with corresponding values. Retrieving a value by its key takes constant time on average, whereas searching an array for a particular element grows linearly with the array’s size. Unlike arrays, dictionaries aren’t ordered; the order in which key-value pairs are enumerated in a for loop is undefined. In the following example, we use a dictionary as the model data for a fictional settings screen in a smartphone app. The screen consists of a list of settings, and each individual setting has a name (the keys in our dictionary) and a value. A value can be one of several data types, such as text, numbers, or Booleans. We use an enum with associated values to model this: enum Setting { case text(String) case int(Int) case bool(Bool) } let defaultSettings: [String:Setting] = [ "Airplane Mode": .bool(false), "Name": .text("My iPhone"), ] defaultSettings["Name"] // Optional(Setting.text("My iPhone")) We use subscripting to get the value of a setting. Dictionary lookup always returns an optional value — when the specified key doesn’t exist, it returns nil. Compare this with arrays, which respond to an out-of-bounds access by crashing the program. Dictionaries also have a subscript that takes an index (in contrast to the commonly used subscript that takes a key) as part of their conformance to the Collection protocol. This subscript traps when called with an invalid index, just like the array subscript does.
  • 48. The rationale for this difference is that array indices and dictionary keys are used very differently. We’ve already seen that it’s quite rare that you actually need to work with array indices directly. And if you do, an array index is usually directly derived from the array in some way (e.g. from a range like 0..<array.count); thus, using an invalid index is a programmer error. On the other hand, it’s very common for dictionary keys to come from some source other than the dictionary being subscripted. Unlike arrays, dictionaries are also sparse. The existence of the value under the key "name" doesn’t tell you anything about whether or not the key “address” also exists. Mutating Dictionaries Just like arrays, dictionaries defined using let are immutable: no entries can be added, removed, or changed. And just like with arrays, we can define a mutable variant using var. To remove a value from a dictionary, we can either set it to nil using subscripting or call removeValue(forKey:). The latter also returns either the deleted value, or nil if the key didn’t exist. If we want to take an immutable dictionary and make changes to it, we have to make a copy: var userSettings = defaultSettings userSettings["Name"] = .text("Jared's iPhone") userSettings["Do Not Disturb"] = .bool(true) Note that, again, the value of defaultSettings didn’t change. As with key removal, an alternative to updating via subscript is the updateValue(_:forKey:) method, which returns the previous value (if any): let oldName = userSettings .updateValue(.text("Jane's iPhone"), forKey: "Name") userSettings["Name"] // Optional(Setting.text("Jane's iPhone")) oldName // Optional(Setting.text("Jared's iPhone")) Some Useful Dictionary Methods What if we wanted to combine the default settings dictionary with any custom settings the user has changed? Custom settings should override defaults, but the resulting dictionary should still include default values for any keys that haven’t been customized. Essentially, we want to merge two dictionaries, where the dictionary that’s being merged in overwrites duplicate keys.
  • 49. Dictionary has a merge(_:uniquingKeysWith:) method, which takes the key-value pairs to be merged in and a function that specifies how to combine two values with the same key. We can use this to merge one dictionary into another, as shown in the following example: var settings = defaultSettings let overriddenSettings: [String:Setting] = ["Name": .text("Jane's iPhone")] settings.merge(overriddenSettings, uniquingKeysWith: { $1 }) settings // ["Name": Setting.text("Jane's iPhone"), "Airplane Mode": Setting.bool(false)] In the example above, we used { $1 } as the policy for combining two values. In other words, if a key exists in both settings and overriddenSettings, we use the value from overriddenSettings. We can also construct a new dictionary out of a sequence of (Key,Value) pairs. If we guarantee that the keys are unique, we can use Dictionary(uniqueKeysWithValues:). However, if we have a sequence where a key can exist multiple times, we need to provide a function to combine two values for the same keys, just like above. For example, to compute how often elements appear in a sequence, we can map over each element, combine it with a 1, and then create a dictionary out of the resulting element-frequency pairs. If we encounter two values for the same key (in other words, if we see the same element more than once), we simply add the frequencies up using +: extension Sequence where Element: Hashable { var frequencies: [Element:Int] { let frequencyPairs = self.map { ($0, 1) } return Dictionary(frequencyPairs, uniquingKeysWith: +) } } let frequencies = "hello".frequencies // ["h": 1, "e": 1, "l": 2, "o": 1] frequencies.filter { $0.value > 1 } // ["l": 2] Another useful method is a map over the dictionary’s values. Because Dictionary is a Sequence, it already has a map method that produces an array. However, sometimes we want to keep the dictionary structure intact and only transform its values. The mapValues method does just this: let settingsAsStrings = settings.mapValues { setting -> String in switch setting { case .text(let text): return text
  • 50. case .int(let number): return String(number) case .bool(let value): return String(value) } } settingsAsStrings // ["Name": "Jane's iPhone", "Airplane Mode": "false"] Hashable Requirement Dictionaries are hash tables. A dictionary assigns each key a position in its underlying storage array based on the key’s hashValue. This is why Dictionary requires its Key type to conform to the Hashable protocol. All the basic data types in the standard library — including strings, integers, floating-point numbers, and Boolean values — already do. Additionally, many other types — like arrays, sets, and optionals — automatically become hashable if their elements are hashable. To maintain their performance guarantees, hash tables require the types stored in them to provide a good hash function that doesn’t produce too many collisions. Writing a good hash function that distributes its inputs uniformly over the full integer range isn’t easy. Fortunately, we almost never have to do this ourselves. The compiler can generate the Hashable conformance in many cases, and even if that doesn’t work for a particular type, the standard library comes with a built-in hash function that custom types can hook into. For structs and enums, Swift can automatically synthesize the Hashable conformance for us as long as they are themselves composed of hashable types. If all stored properties of a struct are hashable, then the struct itself can be conformed to Hashable without us having to write a manual implementation. Similarly, enums that only contain hashable associated values can be conformed for free (enums without associated values even conform to Hashable without declaring this conformance explicitly). Not only does this save initial implementation work, but it also keeps the implementation up to date automatically as properties get added or removed. If you can’t take advantage of the automatic Hashable synthesis (because either you’re writing a class or your custom struct has one or more stored properties that should be ignored for hashing purposes), you first need to make the type Equatable. Then you can implement the hash(into:) requirement of the Hashable protocol (the old pre-Swift 4.2 way of implementing the hashValue property is deprecated). This method receives a Hasher, which wraps a universal hash function and captures the state of the hash function as clients feed data into it. The hasher has a combine method that accepts any hashable value. You should feed all essential components of your type to the hasher by
  • 51. passing them to combine one by one. The essential components are the properties that make up the substance of the type — you’ll usually want to exclude transient properties that can be recreated lazily. You should use the same essential components for equality checking, because the following important invariant must hold: two instances that are equal (as defined by your == implementation) must have the same hash value. The reverse isn’t true: two instances with the same hash value don’t necessarily compare equally. This makes sense, considering there’s only a finite number of distinct hash values, while many hashable types (like strings) have essentially infinite cardinality. The standard library’s universal hash function uses a random seed as one of its inputs. In other words, the hash value of, say, the string "abc" will be different on each program execution. Random seeding is a security measure to protect against targeted hash-flooding denial of service attacks. Since Dictionary and Set iterate over their elements in the order they are stored in the hash table, and since this order is determined by the hash values, this means the same code will produce different iteration orders on each launch. If you need deterministic hashing (e.g. for tests), you can disable random seeding by setting the environment variable SWIFT_DETERMINISTIC_HASHING=1, but you shouldn’t do this in production. Finally, be extra careful when you use types that don’t have value semantics (e.g. mutable objects) as dictionary keys. If you mutate an object after using it as a dictionary key in a way that changes its hash value and/or equality, you won’t be able to find it again in the dictionary. The dictionary now stores the object in the wrong slot, effectively corrupting its internal storage. This isn’t a problem with value types because the key in the dictionary doesn’t share your copy’s storage and therefore can’t be mutated from the outside. Sets The third major collection type in the standard library is Set. A set is an unordered collection of elements, with each element appearing only once. You can essentially think of a set as a dictionary that only stores keys and no values. Like Dictionary, Set is implemented with a hash table and has similar performance characteristics and requirements. Testing a value for membership in a set is a constant-time operation, and set elements must be Hashable, just like dictionary keys.
  • 52. Use a set instead of an array when you need to test efficiently for membership (an O(n) operation for arrays) and the order of the elements is not important, or when you need to ensure that a collection contains no duplicates. Set conforms to the ExpressibleByArrayLiteral protocol, which means we can initialize it with an array literal like this: let naturals: Set = [1, 2, 3, 2] naturals // [2, 3, 1] naturals.contains(3) // true naturals.contains(0) // false Note that the number 2 appears only once in the set; the duplicate never even gets inserted. Like all collections, sets support the common operations we’ve already seen: you can iterate over the elements in a for loop, map or lter them, and do all other sorts of things. Set Algebra As the name implies, Set is closely related to the mathematical concept of a set; it supports all common set operations you learned in math class. For example, we can subtract one set from another: let iPods: Set = ["iPod touch", "iPod nano", "iPod mini", "iPod shuffle", "iPod classic"] let discontinuedIPods: Set = ["iPod mini", "iPod classic", "iPod nano", "iPod shuffle"] let currentIPods = iPods.subtracting(discontinuedIPods) // ["iPod touch"] We can also form the intersection of two sets, i.e. find all elements that are in both: let touchscreen: Set = ["iPhone", "iPad", "iPod touch", "iPod nano"] let iPodsWithTouch = iPods.intersection(touchscreen) // ["iPod touch", "iPod nano"] Or, we can form the union of two sets, i.e. combine them into one (removing duplicates, of course): var discontinued: Set = ["iBook", "PowerBook", "Power Mac"]
  • 53. discontinued.formUnion(discontinuedIPods) discontinued /* ["iPod shuffle", "Power Mac", "iBook", "iPod classic", "PowerBook", "iPod mini", "iPod nano"] */ Here, we used the mutating variant formUnion to mutate the original set (which, as a result, must be declared with var). Almost all set operations have both non-mutating and mutating forms, and the latter have a form prefix. For even more set operations, check out the SetAlgebra protocol. Index Sets and Character Sets Set and OptionSet are the only types in the standard library that conform to SetAlgebra, but this protocol is also adopted by two interesting types in Foundation: IndexSet and CharacterSet. Both of these date back to a time long before Swift was a thing. The way these and other Objective-C classes are now bridged into Swift as fully featured value types — adopting common standard library protocols in the process — is great because they’ll instantly feel familiar to Swift developers. IndexSet represents a set of positive integer values. You can, of course, use a Set<Int> for this task, but IndexSet is more storage efficient because it uses a list of ranges internally. Say you have a table view with 1,000 elements and you want to use a set to manage the indices of the rows the user has selected. A Set<Int> needs to store up to 1,000 elements, depending on how many rows are selected. An IndexSet, on the other hand, stores continuous ranges, so a selection of the first 500 rows in the table only takes two integers to store (the selection’s lower and upper bounds). However, as a user of an IndexSet, you don’t have to worry about the internal structure, as it’s completely hidden behind the familiar SetAlgebra and Collection interfaces. (Unless you want to work on the ranges directly, that is. IndexSet exposes a view to them via its rangeView property, which itself is a collection.) For example, you can add a few ranges to an index set and then map over the indices as if they were individual members: var indices = IndexSet() indices.insert(integersIn: 1..<5) indices.insert(integersIn: 11..<15) let evenIndices = indices.filter { $0 % 2 == 0 } // [2, 4, 12, 14]
  • 54. CharacterSet is an equally efficient way to store a set of Unicode code points. It’s often used to check if a particular string only contains characters from a specific character subset, such as alphanumerics or decimalDigits. However, unlike IndexSet, CharacterSet isn’t a collection. The name CharacterSet, imported from Objective-C, is unfortunate in Swift because CharacterSet isn’t compatible with Swift’s Character type. A better name would be UnicodeScalarSet. We’ll talk more about CharacterSet in the chapter on Strings. Using Sets Inside Closures Dictionaries and sets can be very handy data structures to use inside your functions, even when you’re not exposing them to the caller. For example, if we want to write an extension on Sequence to retrieve all unique elements in the sequence, we could easily put the elements in a set and return its contents. However, that won’t be stable: because a set has no defined order, the input elements might get reordered in the result. To fix this, we can write an extension that maintains the order by using an internal Set for bookkeeping: extension Sequence where Element: Hashable { func unique() -> [Element] { var seen: Set<Element> = [] return filter { element in if seen.contains(element) { return false } else { seen.insert(element) return true } } } } [1,2,3,12,1,3,4,5,6,4,6].unique() // [1, 2, 3, 12, 4, 5, 6] The method above allows us to find all unique elements in a sequence while still maintaining the original order (with the constraint that the elements must be Hashable). Inside the closure we pass to lter, we refer to the variable seen that we defined outside the closure, thus maintaining state over multiple iterations of the closure. In the chapter on Functions, we’ll look at this technique in more detail.
  • 55. Other documents randomly have different content
  • 59. The Project Gutenberg eBook of Addison
  • 60. This ebook is for the use of anyone anywhere in the United States and most other parts of the world at no cost and with almost no restrictions whatsoever. You may copy it, give it away or re-use it under the terms of the Project Gutenberg License included with this ebook or online at www.gutenberg.org. If you are not located in the United States, you will have to check the laws of the country where you are located before using this eBook. Title: Addison Author: William John Courthope Release date: November 27, 2012 [eBook #41496] Most recently updated: October 23, 2024 Language: English Credits: E-text prepared by the Online Distributed Proofreading Team (http://www.pgdp.net) from page images generously made available by Internet Archive (http://archive.org) *** START OF THE PROJECT GUTENBERG EBOOK ADDISON ***
  • 61. The Project Gutenberg eBook, Addison, by William John Courthope Note: Images of the original pages are available through Internet Archive. See http://archive.org/details/addison_00cour English Men of Letters EDITED BY JOHN MORLEY ADDISON BY W. J. COURTHOPE
  • 62. HARPER & BROTHERS PUBLISHERS NEW YORK AND LONDON 1902 ENGLISH MEN OF LETTERS. Edited by John Morley. Johnson Leslie Stephen. Gibbon J. C. Morison. Scott R. H. Hutton. Shelley J. A. Symonds. Hume T. H. Huxley. Goldsmith William Black. Defoe William Minto. Burns J. C. Shairp. Spenser R. W. Church. Thackeray Anthony Trollope. Burke John Morley. Milton Mark Pattison. Hawthorne Henry James, Jr.
  • 63. Southey E. Dowden. Chaucer A. W. Ward. Bunyan J. A. Froude. Cowper Goldwin Smith. Pope Leslie Stephen. Byron John Nichol. Locke Thomas Fowler. Wordsworth F. Myers. Dryden G. Saintsbury. Landor Sidney Colvin. De Quincey David Masson. Lamb Alfred Ainger. Bentley R. C. Jebb. Dickens A. W. Ward. Gray E. W. Gosse. Swift Leslie Stephen. Sterne H. D. Traill. Macaulay J. Cotter Morison. Fielding Austin Dobson. Sheridan Mrs. Oliphant. Addison W. J. Courthope. Bacon R. W. Church. Coleridge H. D. Traill. Sir Philip Sidney J. A. Symonds. Keats Sidney Colvin. Carlyle John Nichol. 12mo, Cloth, 75 cents per volume.
  • 64. Other volumes in preparation. Published by HARPER & BROTHERS, New York. ☞ Any of the above works will be sent by mail, postage prepaid, to any part of the United States, Canada, or Mexico, on receipt of the price.
  • 65. CONTENTS. PAGE CHAPTER I. The State of English Society and Letters after the Restoration 1 CHAPTER II. Addison’s Family and Education 21 CHAPTER III. Addison on His Travels 38 CHAPTER IV. His Employment in Affairs of State 53 CHAPTER V. The “Tatler” and “Spectator” 78 CHAPTER VI. “Cato” 110 CHAPTER VII. Addison’s Quarrel with Pope 125 CHAPTER VIII.
  • 66. The Last Years of His Life 139 CHAPTER IX. The Genius of Addison 153 ADDISON.
  • 67. CHAPTER I. THE STATE OF ENGLISH SOCIETY AND LETTERS AFTER THE RESTORATION. Of the four English men of letters whose writings most fully embody the spirit of the eighteenth century, the one who provides the biographer with the scantiest materials is Addison. In his Journal to Stella, his social verses, and his letters to his friends, we have a vivid picture of those relations with women and that protracted suffering which invest with such tragic interest the history of Swift. Pope, by the publication of his own correspondence, has enabled us, in a way that he never intended, to understand the strange moral twist which distorted a nature by no means devoid of noble instincts. Johnson was fortunate in the companionship of perhaps the best biographer who ever lived. But of the real life and character of Addison scarcely any contemporary record remains. The formal narrative prefixed to his works by Tickell is, by that writer’s own admission, little more than a bibliography. Steele, who might have told us more than any man about his boyhood and his manner of life in London, had become estranged from his old friend before his death. No writer has taken the trouble to preserve any account of the wit and wisdom that enlivened the “little senate” at Button’s. His own letters are, as a rule, compositions as finished as his papers in the Spectator. Those features in his character which excite the greatest interest have been delineated by the hand of an enemy—an enemy who possessed an unrivalled power of satirical portrait-painting, and was restrained by no regard for truth from creating in the public mind such impressions about others as might serve to heighten the favourable opinion of himself.
  • 68. This absence of dramatic incident in Addison’s life would lead us naturally to conclude that he was deficient in the energy and passion which cause a powerful nature to leave a mark upon its age. Yet such a judgment would certainly be erroneous. Shy and reserved as he was, the unanimous verdict of his most illustrious contemporaries is decisive as to the respect and admiration which he excited among them. The man who could exert so potent an influence over the mercurial Steele, who could fascinate the haughty and cynical intellect of Swift, whose conversation, by the admission of his satirist Pope, had in it something more charming than that of any other man; of whom it was said that he might have been chosen king if he wished it; such a man, though to the coarse perception of Mandeville he might have seemed no more than “a parson in a tye- wig,” can hardly have been deficient in force of character. Nor would it have been possible for a writer distinguished by mere elegance and refinement to leave a lasting impress on the literature and society of his country. In one generation after another, men representing opposing elements of rank, class, interest, and taste, have agreed in acknowledging Addison’s extraordinary merits. “Whoever wishes,” says Johnson—at the end of a biography strongly coloured with the prepossessions of a semi-Jacobite Tory—“whoever wishes to attain an English style, familiar but not coarse, and elegant but not ostentatious, must give his days and nights to the volumes of Addison.” “Such a mark of national respect,” says Macaulay, the best representative of middle-class opinion in the present century, speaking of the statue erected to Addison in Westminster Abbey, “was due to the unsullied statesman, to the accomplished scholar, to the master of pure English eloquence, to the consummate painter of life and manners. It was due, above all, to the great satirist who alone knew how to use ridicule without abusing it; who, without inflicting a wound, effected a great social reform, and who reconciled wit and virtue after a long and disastrous separation, during which wit had been led astray by profligacy, and virtue by fanaticism.”
  • 69. This verdict of a great critic is accepted by an age to which the grounds of it are, perhaps, not very apparent. The author of any ideal creation—a poem, a drama, or a novel—has an imprescriptible property in the fame of his work. But to harmonise conflicting social elements, to bring order out of chaos in the sphere of criticism, to form right ways of thinking about questions of morals, taste, and breeding, are operations of which the credit, though it is certainly to be ascribed to particular individuals, is generally absorbed by society itself. Macaulay’s eulogy is as just as it is eloquent, but the pages of the Spectator alone will hardly show the reader why Addison should be so highly praised for having reconciled wit with virtue. Nor, looking at him as a critic, will it appear a great achievement to have pointed out to English society the beauties of Paradise Lost, unless it be remembered that the taste of the preceding generation still influenced Addison’s contemporaries, and that in that generation Cowley was accounted a greater poet than Milton. To estimate Addison at his real value we must regard him as the chief architect of Public Opinion in the eighteenth century. But here again we are met by an initial difficulty, because it has become almost a commonplace of contemporary criticism to represent the eighteenth century as a period of sheer destruction. It is tacitly assumed by a school of distinguished philosophical writers that we have arrived at a stage in the world’s history in which it is possible to take a positive and scientific view of human affairs. As it is of course necessary that from such a system all belief in the supernatural shall be jealously excluded, it has not seemed impossible to write the history of Thought itself in the eighteenth century. And in tracing the course of this supposed continuous stream it is natural that all the great English writers of the period should be described as in one way or another helping to pull down, or vainly to strengthen, the theological barriers erected by centuries of bigotry against the irresistible tide of enlightened progress. It would be of course entirely out of place to discuss here the merits of this new school of history. Those who consider that, whatever
  • 70. glimpses we may obtain of the law and order of the universe, man is, as he always has been and always will be, a mystery to himself, will hardly allow that the operations of the human spirit can be traced in the dissecting-room. But it is, in any case, obvious that to treat the great imaginative writers of any age as if they were only mechanical agents in an evolution of thought is to do them grave injustice. Such writers are, above all things, creative. Their first aim is to “show the very age and body of the time his form and pressure.” No work of the eighteenth century, composed in a consciously destructive spirit, has taken its place among the acknowledged classics of the language. Even the Tale of a Tub is to be regarded as a satire upon the aberrations of theologians from right reason, not upon the principles of Christianity itself. The Essay on Man has, no doubt, logically a tendency towards Deism, but nobody ever read the poem for the sake of its philosophy; and it is well known that Pope was much alarmed when it was pointed out to him that his conclusions might be represented as incompatible with the doctrines of revealed religion. The truth indeed seems to be the exact converse of what is alleged by the scientific historians. So far from the eighteenth century in England being an age of destructive analysis, its energies were chiefly devoted to political, social, and literary reconstruction. Whatever revolution in faith and manners the English nation had undergone had been the work of the two preceding centuries, and though the historic foundations of society remained untouched, the whole form of the superstructure had been profoundly modified. “So tenacious are we,” said Burke, towards the close of the last century, “of our old ecclesiastical modes and fashions of institution that very little change has been made in them since the fourteenth or fifteenth centuries, adhering in this particular as in all else to our old settled maxim never entirely nor at once to depart from antiquity. We found these institutions on the whole favourable to morality and discipline, and we thought they were susceptible of amendment without altering the ground. We thought they were
  • 71. capable of receiving and meliorating, and, above all, of preserving the accessories of science and literature as the order of Providence should successively produce them. And after all, with this Gothic and monkish education (for such it is the groundwork), we may put in our claim to as ample and early a share in all the improvements in science, in arts, and in literature which have illuminated the modern world as any other nation in Europe. We think one main cause of this improvement was our not despising the patrimony of knowledge which was left us by our forefathers.” All this is, in substance, true of our political as well as our ecclesiastical institutions. And yet, when Burke wrote, the great feudal and mediæval structure of England had been so transformed by the Wars of the Roses, the Reformation, the Rebellion, and the Revolution, that its ancient outlines were barely visible. In so far, therefore, as his words seem to imply that the social evolution he describes was produced by an imperceptible and almost mechanical process of national instinct, the impression they tend to create is entirely erroneous. If we have been hitherto saved from such corruption as undermined the republics of Italy, from the religious wars that so long enfeebled and divided Germany, and from the Revolution that has severed modern France from her ancient history, thanks for this are due partly, no doubt, to favouring conditions of nature and society, but quite as much to the genius of great individuals who prepared the mind of the nation for the gradual assimilation of new ideas. Thus Langland and Wycliffe and their numerous followers, long before the Reformation, had so familiarised the minds of the people with their ideas of the Christian religion that the Sovereign was able to assume the Headship of the Church without the shock of a social convulsion. Fresh feelings and instincts grew up in the hearts of whole classes of the nation without at first producing any change in outward habits of life, and even without arousing a sense of their logical incongruity. These mixed ideas were constantly brought before the imagination in the works of the poets. Shakespeare abounds with passages in
  • 72. which, side by side with the old feudal, monarchical, catholic, and patriotic instincts of Englishmen, we find the sentiments of the Italian Renaissance. Spenser conveys Puritan doctrines sometimes by the mouth of shepherds, whose originals he had found in Theocritus and Virgil; sometimes under allegorical forms derived from books of chivalry and the ceremonial of the Catholic Church. Milton, the most rigidly Calvinistic of all the English poets in his opinions, is also the most severely classical in his style. It was the task of Addison to carry on the reconciling traditions of our literature. It is his praise to have accomplished his task under conditions far more difficult than any that his predecessors had experienced. What they had done was to give instinctive and characteristic expression to the floating ideas of the society about them; what Addison and his contemporaries did was to found a public opinion by a conscious effort of reason and persuasion. Before the Civil Wars there had been at least no visible breach in the principle of Authority in Church and State. At the beginning of the eighteenth century constituted authority had been recently overthrown; one king had been beheaded, another had been expelled; the Episcopalian form of Church Government had been violently displaced in favour of the Presbyterian, and had been with almost equal violence restored. Whole classes of the population had been drawn into opposing camps during the Civil War, and still stood confronting each other with all the harsh antagonism of sentiment inherited from that conflict. Such a bare summary alone is sufficient to indicate the nature of the difficulties Addison had to encounter in his efforts to harmonise public opinion; but a more detailed examination of the state of society after the Restoration is required to place in its full light the extraordinary merits of the success that he achieved. There was, to begin with, a vehement opposition between town and country. In the country the old ideas of Feudalism, modified by circumstances, but vigorous and deep-rooted, still prevailed. True, the military system of land-tenure had disappeared with the
  • 73. Restoration, but it was not so with the relations of life, and the habits of thought and feeling which the system had created. The features of surviving Feudalism have been inimitably preserved for us in the character of Sir Roger de Coverley. Living in the patriarchal fashion, in the midst of tenants and retainers, who looked up to him as their chief, and for whose welfare and protection he considered himself responsible, the country gentleman valued above all things the principle of Loyalty. To the moneyed classes in the towns he was instinctively opposed; he regarded their interests, both social and commercial, as contrary to his own; he looked with dislike and suspicion on the economical principles of government and conduct on which these classes naturally rely. Even the younger sons of county families had in Addison’s day abandoned the custom, common enough in the feudal times, of seeking their fortune in trade. Many a Will Wimble now spent his whole life in the country, training dogs for his neighbours, fishing their streams, making whips for their young heirs, and even garters for their wives and daughters.[1] The country gentlemen were confirmed in these ideas by the difficulties of communication. During his visit to Sir Roger de Coverley the Spectator observed the extreme slowness with which fashions penetrated into the country; and he noticed, too, that party spirit was much more violent there than in the towns. The learning of the clergy, many of whom resided with the country squires as chaplains, was of course enlisted on the Tory side, and supplied it with arguments which the body of the party might perhaps have found it difficult to discover, or at least to express, for themselves. For Tory tastes undoubtedly lay generally rather in the direction of sport than of books. Sir Roger seems to be as much above the average level of his class as Squire Western is certainly below it: perhaps the Tory fox-hunter of the Freeholder, though somewhat satirically painted, is a fair representative of the society which had its headquarters at the October Club, and whose favourite poet was Tom D’Urfey.
  • 74. The commercial and professional classes, from whom the Whigs derived their chief support, of course predominated in the towns, and their larger opportunities of association gave them an influence in affairs which compensated for their inferiority in numbers. They lacked, however, what the country party possessed, a generous ideal of life. Though many of them were connected with the Presbyterian system, their common sense made them revolt from its rigidity, while at the same time their economical principles failed to supply them with any standard that could satisfy the imagination. Sir Andrew Freeport excites in us less interest than any member of the Spectator’s Club. There was not yet constituted among the upper middle classes that mixed conception of good feeling, good breeding, and good taste which we now attach to the name of “gentleman.” Two main currents of opinion divided the country, to one of which a man was obliged to surrender himself if he wished to enjoy the pleasures of organised society. One of these was Puritanism, but this was undoubtedly the less popular, or at least the less fashionable. A protracted experience of Roundhead tyranny under the Long Parliament had inclined the nation to believe that almost any form of Government was preferable to that of the Saints. The Puritan, no longer the mere sectarian, as in the days of Elizabeth and James I., somewhat ridiculous in the extravagance of his opinions, but respectable from the constancy with which he maintained them, had ruled over them as a taskmaster, and had forced them, as far as he could by military violence, to practise the asceticism to which monks and nuns had voluntarily submitted themselves. The most innocent as well as the most brutal diversions of the people were sacrificed to his spiritual pride. As Macaulay well says, he hated bear-baiting, not because it gave pain to the bear, but because it gave pleasure to the spectator. The tendency of his creed was, in fact, anti-social. Beauty in his eyes was a snare, and pleasure a sin; the only mode of social intercourse which he approved was a sermon.
  • 75. On the other hand, the habits of the Court, which gave the tone to all polite society, were almost equally distasteful to the instincts of the people. It was inevitable that the inclinations of Charles II. should be violently opposed to every sentiment of the Puritans. While he was in the power of the Scots he had been forced into feigned compliance with Presbyterian rites; the Puritans had put his father to death, and had condemned himself to many years of exile and hardship in Catholic countries. He had returned to his own land half French in his political and religious sympathies, and entirely so in his literary tastes. To convert and to corrupt those of his subjects who immediately surrounded him was an easy matter. “All by the king’s example lived and loved.” Poets, painters, and actors were forward to promote principles viewed with favour by their sovereign and not at all disagreeable to themselves. An ingenious philosopher elevated Absolutism into an intellectual and moral system, the consequence of which was to encourage the powerful in the indulgence of every selfish instinct. As the Puritans had oppressed the country with a system of inhuman religion and transcendental morality, so now, in order to get as far from Puritanism as possible, it seemed necessary for every one aspiring to be thought a gentleman to avow himself an atheist or a debauchee. The ideas of the man in the mode after the Restoration are excellently hit off in one of the fictitious letters in the Spectator: “I am now between fifty and sixty, and had the honour to be well with the first men of taste and gallantry in the joyous reign of Charles the Second. As for yourself, Mr. Spectator, you seem with the utmost arrogance to undermine the very fundamentals upon which we conducted ourselves. It is monstrous to set up for a man of wit and yet deny that honour in a woman is anything but peevishness, that inclination is not the best rule of life, or virtue and vice anything else but health and disease. We had no more to do but to put a lady in a good humour, and all we could wish followed of course. Then, again,
  • 76. your Tully and your discourses of another life are the very bane of mirth and good humour. Prythee, don’t value thyself on thy reason at that exorbitant rate and the dignity of human nature; take my word for it, a setting dog has as good reason as any man in England.”[2] While opinions, which from different sides struck at the very roots of society, prevailed both in the fashionable and religious portions of the community, it was inevitable that Taste should be hopelessly corrupt. All the artistic and literary forms which the Court favoured were of the romantic order, but it was romance from which beauty and vitality had utterly disappeared. Of the two great principles of ancient chivalry, Love and Honour, the last notes of which are heard in the lyrics of Lovelace and Montrose, one was now held to be non- existent, and the other was utterly perverted. The feudal spirit had surrounded woman with an atmosphere of mystical devotion, but in the reign of Charles II. the passion of love was subjected to the torturing treatment then known as “wit.” Cowley and Waller seem to think that when a man is in love the energy of his feelings is best shown by discovering resemblances between his mistress and those objects in nature to which she is apparently most unlike. The ideal of Woman, as she is represented in the Spectator, adding grace, charity, and refinement to domestic life, had still to be created. The king himself, the presumed mirror of good taste, was notoriously under the control of his numerous mistresses; and the highest notion of love which he could conceive was gallantry. French romances were therefore generally in vogue. All the casuistry of love which had been elaborated by Mademoiselle de Scudery was reproduced with improvements by Mrs. Aphra Behn. At the same time, as usually happens in diseased societies, there was a general longing to cultivate the simplicity of the Golden Age, and the consequence was that no person, even in the lower grades of society, who pretended to any reading, ever thought of making love in his own person. The proper tone of feeling was not acquired till he
  • 77. had invested himself with the pastoral attributes of Damon and Celadon, and had addressed his future wife as Amarantha or Phyllis. The tragedies of the period illustrate this general inclination to spurious romance. If ever there was a time when the ideal of monarchy was degraded, and the instincts of chivalrous action discouraged, it was in the reign of Charles II. Absorbed as he was in the pursuit of pleasure, the king scarcely attempted to conceal his weariness when obliged to attend to affairs of State. He allowed the Dutch fleet to approach his capital and to burn his own ships of war on the Thames; he sold Dunkirk to the French; hardly any action in his life evinces any sense of patriotism or honour. And yet we have only to glance at Johnson’s Life of Dryden to see how all the tragedies of the time turn on the great characters, the great actions, the great sufferings of princes. The Elizabethan drama had exhibited man in every degree of life and with every variety of character; the playwright of the Restoration seldom descended below such themes as the conquest of Mexico or Granada, the fortunes of the Great Mogul, and the fate of Hannibal. This monotony of subject was doubtless in part the result of policy, for in pitying the fortunes of Montezuma the imagination of the spectator insensibly recalled those of Charles the Second. Everything in these tragedies is unreal, strained, and affected. In order to remove them as far as possible from the language of ordinary life they are written in rhyme, while the astonishment of the audience is raised with big swelling words, which vainly seek to hide the absence of genuine feeling. The heroes tear their passion to tatters because they think it heroic to do so; their flights into the sublime generally drop into the ridiculous; instead of holding up the mirror to nature, their object is to depart as far as possible from common sense. Nothing exhibits more characteristically the utterly artificial feeling, both of the dramatists and the spectators, than the habit which then prevailed of dismissing the audience after a tragic play with a witty epilogue. On one occasion, Nell Gwynne, in the character of St. Catherine, was, at the end of the play, left for dead
  • 78. upon the stage. Her body having to be removed, the actress suddenly started to her feet, exclaiming, “Hold! are you mad? you damned confounded dog, I am to rise and speak the epilogue!”[3] By way of compensation, however, the writers of the period poured forth their real feelings without reserve in their comedies. So great, indeed, is the gulf that separates our own manners from theirs, that some critics have endeavoured to defend the comic dramatists of the Restoration against the moralists on the ground that their representations of Nature are entirely devoid of reality. Charles Lamb, who loved all curiosities, and the Caroline comedians among the number, says of them: “They are a world of themselves almost as much as fairy- land. Take one of their characters, male or female (with few exceptions they are alike), and place it in a modern play, and my virtuous indignation shall rise against the profligate wretch as warmly as the Catos of the pit could desire, because in a modern play I am to judge of the right and the wrong. The standard of police is the measure of political justice. The atmosphere will blight it; it cannot live here. It has got into a moral world, where it has no business, from which it must needs fall headlong— as dizzy and incapable of making a stand as a Swedenborgian bad spirit that has wandered unawares into his sphere of Good Men or Angels. But in its own world do we feel the creature is so very bad? The Fainalls and Mirabels, the Dorimants and Lady Touchwoods, in their own sphere do not offend my moral sense; in fact, they do not appeal to it at all. They seem engaged in their proper element. They break through no laws or conscientious restraints. They know of none. They have got out of Christendom into the land of-what shall I call it? —of cuckoldry—the Utopia of gallantry, where pleasure is duty and the manners perfect freedom. It is altogether a
  • 79. speculative scene of things, which has no reference whatever to the world that is.” This is a very happy description of the manner in which the plays of Etherege, Shadwell, Wycherley, and Congreve affect us to-day; and it is no doubt superfluous to expend much moral indignation on works which have long since lost their power to charm: comedies in which the reader finds neither the horseplay of Aristophanes, nor the nature of Terence, nor the poetry of Shakespeare; in which there is not a single character that arouses interest, or a situation that spontaneously provokes laughter; in which the complications of plot are produced by the devices of fine gentlemen for making cuckolds of citizens, and the artifices of wives to dupe their husbands; in which the profuse wit of the dialogue might excite admiration, if it were possible to feel the smallest interest in the occasion that produced it. But to argue that these plays never represented any state of existing society is a paradox which chooses to leave out of account the contemporary attack on the stage made by Jeremy Collier, the admissions of Dryden, and all those valuable glimpses into the manners of our ancestors which are afforded by the prologues of the period. It is sufficient to quote against Lamb the witty and severe criticism of Steele in the Spectator, upon Etherege’s Man of the Mode: “It cannot be denied but that the negligence of everything which engages the attention of the sober and valuable part of mankind appears very well drawn in this piece. But it is denied that it is necessary to the character of a fine gentleman that he should in that manner trample upon all order and decency. As for the character of Dorimant, it is more of a coxcomb than that of Fopling. He says of one of his companions that a good correspondence between them is their mutual interest. Speaking of that friend, he declares their being much together ‘makes the women think the better of his understanding, and judge more favourably of my reputation. It makes him pass upon some for a man of very good sense, and me upon others for a very civil person.’ This whole celebrated piece is a
  • 80. perfect contradiction to good manners, good sense, and common honesty; and as there is nothing in it but what is built upon the ruin of virtue and innocence, according to the notion of virtue in this comedy, I take the shoemaker to be in reality the fine gentleman of the play; for it seems he is an atheist, if we may depend upon his character as given by the orange-woman, who is herself far from being the lowest in the play. She says of a fine man who is Dorimant’s companion, ‘there is not such another heathen in the town except the shoemaker.’ His pretension to be the hero of the drama appears still more in his own description of his way of living with his lady. ‘There is,’ says he, ‘never a man in the town lives more like a gentleman with his wife than I do. I never mind her motions; she never inquires into mine. We speak to one another civilly; hate one another heartily; and, because it is vulgar to lie and soak together, we have each of us our several settle-beds.’ “That of ‘soaking together’ is as good as if Dorimant had spoken it himself; and I think, since he puts human nature in as ugly a form as the circumstances will bear, and is a staunch unbeliever, he is very much wronged in having no part of the good fortune bestowed in the last act. To speak plain of this whole work, I think nothing but being lost to a sense of innocence and virtue can make any one see this comedy without observing more frequent occasion to move sorrow and indignation than mirth and laughter. At the same time I allow it to be nature, but it is nature in its utmost corruption and degeneracy.”[4] The truth is, that the stage after the Restoration reflects only too faithfully the manners and the sentiments of the only society which at that period could boast of anything like organisation. The press, which now enables public opinion to exercise so powerful a control over the manners of the times, had then scarcely an existence. No standard of female honour restrained the license of wit and debauchery. If the clergy were shocked at the propagation of ideas so contrary to the whole spirit of Christianity, their natural impulse to reprove them was checked by the fear that an apparent
  • 81. condemnation of the practices of the Court might end in the triumph of their old enemies, the Puritans. All the elements of an old and decaying form of society that tended to atheism, cynicism, and dissolute living, exhibited themselves, therefore, in naked shamelessness on the stage. The audiences in the theatres were equally devoid of good manners and good taste; they did not hesitate to interrupt the actors in the midst of a serious play, while they loudly applauded their obscene allusions. So gross was the character of comic dialogue that women could not venture to appear at a comedy without masks, and under these circumstances the theatre became the natural centre for assignations. In such an atmosphere women readily cast off all modesty and reserve; indeed, the choicest indecencies of the times are to be found in the epilogues to the plays, which were always assigned to the female actors. It at first sight seems remarkable that a society inveterately corrupt should have contained in itself such powers of purification and vitality as to discard the literary garbage of the Restoration period in favour of the refined sobriety which characterises the writers of Queen Anne’s reign. But, in fact, the spread of the infection was confined within certain well-marked limits. The Court moved in a sphere apart, and was altogether too light and frivolous to exert a decided moral influence on the great body of the nation. The country gentlemen, busied on their estates, came seldom to town; the citizens, the lawyers, and the members of the other professions steadily avoided the theatre, and regarded with equal contempt the moral and literary excesses of the courtiers. Among this class, unrepresented at present in the world of letters, except, perhaps, by antiquarians like Selden, the foundations of sound taste were being silently laid. The readers of the nation had hitherto been almost limited to the nobility. Books were generally published by subscription, and were dependent for their success on the favour with which they were received by the courtiers. But, after the subsidence of the Civil War, the nation began to make rapid strides in wealth and refinement, and the moneyed classes sought for
  • 82. intellectual amusement in their leisure hours. Authors by degrees found that they might look for readers beyond the select circle of their aristocratic patrons; and the book-seller, who had hitherto calculated his profits merely by the commission he might obtain on the sale of books, soon perceived that they were becoming valuable as property. The reign of Charles II. is remarkable not only for the great increase in the number of the licensed printers in London, but for the appearance of the first of the race of modern publishers, Jacob Tonson. The portion of society whose tastes the publishers undertook to satisfy was chiefly interested in history, poetry, and criticism. It was this for which Dryden composed his Miscellany, this to which he addressed the admirable critical essays which precede his Translations from the Latin Poets and his Versifications of Chaucer, and this which afterwards gave the main support to the Tatler and the Spectator. Ignorant of the writings of the great classical authors, as well as of the usages of polite society, these men were nevertheless robust and manly in their ideas, and were eager to form for themselves a correct standard of taste by reference to the best authorities. Though they turned with repugnance from the playhouse and from the morals of the Court, they could not avoid being insensibly affected by the tone of grace and elegance which prevailed in Court circles. And in this respect, if in no other, our gratitude is due to the Caroline dramatists, who may justly claim to be the founders of the social prose style in English literature. Before them English prose had been employed, no doubt, with music and majesty by many writers; but the style of these is scarcely representative; they had used the language for their own elevated purposes, without, however, attempting to give it that balanced fineness and subtlety which makes it a fitting instrument for conveying the complex ideas of an advanced stage of society. Dryden, Wycherley, and their followers, impelled by the taste of the Court to study the French language, brought to English composition a nicer standard of logic and a more choice selection of language, while the necessity of pleasing their audiences with brilliant dialogue
  • 83. made them careful to give their sentences that well-poised structure which Addison afterwards carried to perfection in the Spectator. By this brief sketch the reader may be enabled to judge of the distracted state of society, both in politics and taste, in the reign of Charles II. On the one side, the Monarchical element in the Constitution was represented by the Court Party, flushed with the recent restoration; retaining the old ideas and principles of absolutism which had prevailed under James I., without being able to perceive their inapplicability to the existing nature of things; feeding its imagination alternately on sentiments derived from the decayed spirit of chivalry, and on artistic representations of fashionable debauchery in its most open form—a party which, while it fortunately preserved the traditions of wit, elegance, and gaiety of style, seemed unaware that these qualities could be put to any other use than the mitigation of an intolerable ennui. On the other side, the rising power of Democracy found its representatives in austere Republicans opposed to all institutions in Church and State that seemed to obstruct their own abstract principles of government; gloomy fanatics, who, with an intense intellectual appreciation of eternal principles of religion and morality, sought to sacrifice to their system the most permanent and even innocent instincts of human nature. Between the two extreme parties was the unorganised body of the nation, grouped round old customs and institutions, rapidly growing in wealth and numbers, conscious of the rise in their midst of new social principles, but perplexed how to reconcile these with time-honoured methods of religious, political, and literary thought. To lay the foundations of sound opinion among the people at large; to prove that reconciliation was possible between principles hitherto exhibited only in mutual antagonism; to show that under the English Constitution monarchy, aristocracy, and democracy might all be harmonised, that humanity was not absolutely incompatible with religion or morality with art, was the task of the statesmen, and still more of the men of letters, of the early part of the eighteenth century.
  • 85. CHAPTER II. ADDISON’S FAMILY AND EDUCATION. Joseph Addison was born on the 1st of May, 1672. He was the eldest son of Lancelot Addison, at the time of his birth rector of Milston, near Amesbury, in Wiltshire, and afterwards Dean of Lichfield. His father was a man of character and accomplishments. Educated at Oxford, while that University was under the control of the famous Puritan Visitation, he made no secret of his contempt for principles to which he was forced to submit, or of his preferences for Monarchy and Episcopacy. His boldness was not agreeable to the University authorities, and being forced to leave Oxford, he maintained himself for a time near Petworth, in Sussex, by acting as chaplain or tutor in families attached to the Royalist cause. After the Restoration he obtained the appointment of chaplain to the garrison of Dunkirk, and when that town was ceded to France in 1662, he was removed in a similar capacity to Tangier. Here he remained eight years, but, venturing on a visit to England, his post was bestowed upon another, and he would have been left without resources had not one of his friends presented him with the living of Milston, valued at £120 a year. With the courage of his order he thereupon took a wife, Jane, daughter of Dr. Nathaniel Gulston, and sister of William Gulston, Bishop of Bristol, by whom he had six children, three sons and three daughters, all born at Milston. In 1675 he was made a prebendary of Salisbury Cathedral and Chaplain-in-Ordinary to the King; and in 1683 he was promoted to the Deanery of Lichfield, as a reward for his services at Tangier, and out of consideration of losses which he had sustained by a fire at Milston. His literary reputation stood high, and it is said that he would have been made a bishop, if his old zeal
  • 86. for legitimacy had not prompted him to manifest in the Convocation of 1689 his hostility to the Revolution. He died in 1703. Lancelot was a writer at once voluminous and lively. In the latter part of his life he produced several treatises on theological subjects, the most popular of which was called An Introduction to the Sacrament. This book passed through many editions. The doctrine it contains leans rather to the Low Church side. But much the most characteristic of his writings were his works on Mahommedanism and Judaism, the results of his studies during his residence in Barbary. These show not only considerable industry and research and powers of shrewd observation, but that genuine literary faculty which enables a writer to leave upon a subject of a general nature the impression of his own character. While there is nothing forced or exaggerated in his historical style, a vein of allegory runs through the narrative of the Revolutions of the Kingdoms of Fez and Morocco, which must have had a piquant flavour for the orthodox English reader of that day. Recollections of the Protectorate would have taken nothing of its vividness from the portrait of the Moorish priest who “began to grow into reputation with the people by reason of his high pretensions to piety and fervent zeal for their law, illustrated by a stubborn rigidity of conversation and outward sanctity of life.” When the Zeriffe, with ambitious designs on the throne, sent his sons on a pilgrimage to Mecca, the religious buffooneries practised by the young men must have recalled to the reader circumstances more recent and personal than those which the author was apparently describing. “Much was the reverence and reputation of holiness which they thereby acquired among the superstitious people, who could hardly be kept from kissing their garments and adoring them as saints, while they failed not in their parts, but acted as much devotion as high contemplative looks, deep sighs, tragical gestures, and other passionate interjections of holiness could express. ‘Allah, allah!’ was their doleful note, their sustenance the people’s alms.” And when these impostors had inveigled the King of Fez into a religious war, the description of those who “mistrusted their own safety, and began, but too late, to repent
  • 87. Welcome to our website – the perfect destination for book lovers and knowledge seekers. We believe that every book holds a new world, offering opportunities for learning, discovery, and personal growth. That’s why we are dedicated to bringing you a diverse collection of books, ranging from classic literature and specialized publications to self-development guides and children's books. More than just a book-buying platform, we strive to be a bridge connecting you with timeless cultural and intellectual values. With an elegant, user-friendly interface and a smart search system, you can quickly find the books that best suit your interests. Additionally, our special promotions and home delivery services help you save time and fully enjoy the joy of reading. Join us on a journey of knowledge exploration, passion nurturing, and personal growth every day! ebookbell.com