It’s hard to imagine a crueler arrangement: not only are our four thousand weeks constantly running out, but the fewer of them we have left, the faster we seem to lose them.
In the modern world, the American anthropologist Edward T. Hall once pointed out, time feels like an unstoppable conveyor belt, bringing us new tasks as fast as we can dispatch the old ones; and becoming “more productive” just seems to cause the belt to speed up.
Productivity is a trap. Becoming more efficient just makes you more rushed, and trying to clear the decks simply makes them fill up again faster.
Part I: Choosing to Choose
1. The Limit-Embracing Life
The real problem isn’t our limited time. The real problem - or so I hope to convince you - is that we’ve unwittingly inherited, and feel pressured to live by, a troublesome set of ideas about how to use our limited time, all of which are pretty much guaranteed to make things worse.
From thinking about time in the abstract, it’s natural to start treating it as a resource, something to be bought and sold and used as efficiently as possible, like coal or iron or any other raw material.
Afterward, once “time” and “life” had been separated in most people’s minds, time became a thing that you used - and it’s this shift taht serves as the precondition for all the uniquely modern ways in which we struggle with time today. Once time is a resource to be used, you start to feel presure, whether from external forces or from yourself, to use it well, and to berate yourself when you feel you’ve wasted it. When you’re faced with too many demands, it’s easy to assume that the only answer must be to make better use of time, by becoming more efficient, driving yourself harder, or working for longer - as if you were a machine in the Industrial Revolution - instead of asking whether the demands themselves might be unreasonable. It grows alluring to try to multitask - that is, to use the same portion of time for two things at once, as the German philosopher Friedrich Nietzsche was one of the first to notice: “One thinks with a watch in one’s hand,” he complained in an 1887 essay, “even as one eats one’s midday meal while reading the latest news of the stock market.”
As this modern mindset came to dominate, wrote Mumford, “Eternity ceased gradually to serve as the measure and focus of human actions.” In its place came the dictatorship of the clock, the schedule, and the Google Calendar alert; Marilynne Robinson’s “joyless urgency” and the constant feeling that you ought to be getting more done. The troublewith attempting to master your time, it turns out, is that time ends up mastering you.
/// A publisher that never publishes any values, and optionally finishes immediately. /// /// You can create a ”Never” publisher — one which never sends values and never finishes or fails — with the initializer `Empty(completeImmediately: false)`. @available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) publicstructEmpty<Output, Failure> : Publisher, EquatablewhereFailure : Error{
/// Creates an empty publisher. /// /// - Parameter completeImmediately: A Boolean value that indicates whether the publisher should immediately finish. publicinit(completeImmediately: Bool = true)
/// Creates an empty publisher with the given completion behavior and output and failure types. /// /// Use this initializer to connect the empty publisher to subscribers or other publishers that have specific output and failure types. /// /// - Parameters: /// - completeImmediately: A Boolean value that indicates whether the publisher should immediately finish. /// - outputType: The output type exposed by this publisher. /// - failureType: The failure type exposed by this publisher. publicinit(completeImmediately: Bool = true, outputType: Output.Type, failureType: Failure.Type)
/// A Boolean value that indicates whether the publisher immediately sends a completion. /// /// If `true`, the publisher finishes immediately after sending a subscription to the subscriber. If `false`, it never completes. publiclet completeImmediately: Bool
/// Attaches the specified subscriber to this publisher. /// /// Implementations of ``Publisher`` must implement this method. /// /// The provided implementation of ``Publisher/subscribe(_:)-4u8kn``calls this method. /// /// - Parameter subscriber: The subscriber to attach to this ``Publisher``, after which it can receive values. publicfuncreceive<S>(subscriber: S)whereOutput == S.Input, Failure == S.Failure, S : Subscriber
/// Returns a Boolean value that indicates whether two publishers are equivalent. /// - Parameters: /// - lhs: An `Empty` instance to compare. /// - rhs: Another `Empty` instance to compare. /// - Returns: `true` if the two publishers have equal `completeImmediately` properties; otherwise `false`. publicstaticfunc == (lhs: Empty<Output, Failure>, rhs: Empty<Output, Failure>) -> Bool }
/// A publisher that emits an output to each subscriber just once, and then finishes. /// /// You can use a ``Just`` publisher to start a chain of publishers. A ``Just`` publisher is also useful when replacing a value with ``Publishers/Catch``. /// /// In contrast with <doc://com.apple.documentation/documentation/Swift/Result/Publisher>, a ``Just`` publisher can’t fail with an error. And unlike <doc://com.apple.documentation/documentation/Swift/Optional/Publisher>, a ``Just`` publisher always produces a value. @available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) publicstructJust<Output> : Publisher{
/// The kind of errors this publisher might publish. /// /// Use `Never` if this `Publisher` does not publish errors. publictypealiasFailure = Never
/// The one element that the publisher emits. publiclet output: Output
/// Initializes a publisher that emits the specified output just once. /// /// - Parameter output: The one element that the publisher emits. publicinit(_ output: Output)
/// Attaches the specified subscriber to this publisher. /// /// Implementations of ``Publisher`` must implement this method. /// /// The provided implementation of ``Publisher/subscribe(_:)-4u8kn``calls this method. /// /// - Parameter subscriber: The subscriber to attach to this ``Publisher``, after which it can receive values. publicfuncreceive<S>(subscriber: S)whereOutput == S.Input, S : Subscriber, S.Failure == Just<Output>.Failure }
/// A publisher that eventually produces a single value and then finishes or fails. @available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) finalpublicclassFuture<Output, Failure> : PublisherwhereFailure : Error{
/// A type that represents a closure to invoke in the future, when an element or error is available. /// /// The promise closure receives one parameter: a `Result` that contains either a single element published by a ``Future``, or an error. publictypealiasPromise = (Result<Output, Failure>) -> Void
/// Creates a publisher that invokes a promise closure when the publisher emits an element. /// /// - Parameter attemptToFulfill: A ``Future/Promise`` that the publisher invokes when the publisher emits an element or terminates with an error. publicinit(_ attemptToFulfill: @escaping (@escaping Future<Output, Failure>.Promise) -> Void)
/// Attaches the specified subscriber to this publisher. /// /// Implementations of ``Publisher`` must implement this method. /// /// The provided implementation of ``Publisher/subscribe(_:)-4u8kn``calls this method. /// /// - Parameter subscriber: The subscriber to attach to this ``Publisher``, after which it can receive values. finalpublicfuncreceive<S>(subscriber: S)whereOutput == S.Input, Failure == S.Failure, S : Subscriber }
/// A publisher that awaits subscription before running the supplied closure to create a publisher for the new subscriber. @available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) publicstructDeferred<DeferredPublisher> : PublisherwhereDeferredPublisher : Publisher{
/// The kind of values published by this publisher. publictypealiasOutput = DeferredPublisher.Output
/// The kind of errors this publisher might publish. publictypealiasFailure = DeferredPublisher.Failure
/// The closure to execute when this deferred publisher receives a subscription. /// /// The publisher returned by this closure immediately receives the incoming subscription. publiclet createPublisher: () -> DeferredPublisher
/// Creates a deferred publisher. /// /// - Parameter createPublisher: The closure to execute when calling `subscribe(_:)`. publicinit(createPublisher: @escaping () -> DeferredPublisher)
/// Attaches the specified subscriber to this publisher. /// /// Implementations of ``Publisher`` must implement this method. /// /// The provided implementation of ``Publisher/subscribe(_:)-4u8kn``calls this method. /// /// - Parameter subscriber: The subscriber to attach to this ``Publisher``, after which it can receive values. publicfuncreceive<S>(subscriber: S)whereS : Subscriber, DeferredPublisher.Failure == S.Failure, DeferredPublisher.Output == S.Input }
/// A publisher that immediately terminates with the specified error. @available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) publicstructFail<Output, Failure> : PublisherwhereFailure : Error{
/// Creates a publisher that immediately terminates with the specified failure. /// /// - Parameter error: The failure to send when terminating the publisher. publicinit(error: Failure)
/// Creates publisher with the given output type, that immediately terminates with the specified failure. /// /// Use this initializer to create a `Fail` publisher that can work with subscribers or publishers that expect a given output type. /// /// - Parameters: /// - outputType: The output type exposed by this publisher. /// - failure: The failure to send when terminating the publisher. publicinit(outputType: Output.Type, failure: Failure)
/// The failure to send when terminating the publisher. publiclet error: Failure
/// Attaches the specified subscriber to this publisher. /// /// Implementations of ``Publisher`` must implement this method. /// /// The provided implementation of ``Publisher/subscribe(_:)-4u8kn``calls this method. /// /// - Parameter subscriber: The subscriber to attach to this ``Publisher``, after which it can receive values. publicfuncreceive<S>(subscriber: S)whereOutput == S.Input, Failure == S.Failure, S : Subscriber }
/// A publisher that publishes a given sequence of elements. /// /// When the publisher exhausts the elements in the sequence, the next request causes the publisher to finish. publicstructSequence<Elements, Failure> : PublisherwhereElements : Sequence, Failure : Error{
/// The kind of values published by this publisher. publictypealiasOutput = Elements.Element
/// The sequence of elements to publish. publiclet sequence: Elements
/// Creates a publisher for a sequence of elements. /// /// - Parameter sequence: The sequence of elements to publish. publicinit(sequence: Elements)
/// Attaches the specified subscriber to this publisher. /// /// Implementations of ``Publisher`` must implement this method. /// /// The provided implementation of ``Publisher/subscribe(_:)-4u8kn``calls this method. /// /// - Parameter subscriber: The subscriber to attach to this ``Publisher``, after which it can receive values. publicfuncreceive<S>(subscriber: S)whereFailure == S.Failure, S : Subscriber, Elements.Element == S.Input } }
/// A publisher that allows for recording a series of inputs and a completion, for later playback to each subscriber. @available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) publicstructRecord<Output, Failure> : PublisherwhereFailure : Error{
/// The recorded output and completion. publiclet recording: Record<Output, Failure>.Recording
/// Creates a publisher to interactively record a series of outputs and a completion. /// /// - Parameter record: A recording instance that can be retrieved after completion to create new record publishers to replay the recording. publicinit(record: (inoutRecord<Output, Failure>.Recording) -> Void)
/// Creates a record publisher from an existing recording. /// /// - Parameter recording: A previously-recorded recording of published elements and a completion. publicinit(recording: Record<Output, Failure>.Recording)
/// Creates a record publisher to publish the provided elements, followed by the provided completion value. /// /// - Parameters: /// - output: An array of output elements to publish. /// - completion: The completion value with which to end publishing. publicinit(output: [Output], completion: Subscribers.Completion<Failure>)
/// Attaches the specified subscriber to this publisher. /// /// Implementations of ``Publisher`` must implement this method. /// /// The provided implementation of ``Publisher/subscribe(_:)-4u8kn``calls this method. /// /// - Parameter subscriber: The subscriber to attach to this ``Publisher``, after which it can receive values. publicfuncreceive<S>(subscriber: S)whereOutput == S.Input, Failure == S.Failure, S : Subscriber
/// A recorded sequence of outputs, followed by a completion value. publicstructRecording{
publictypealiasInput = Output
/// The output which will be sent to a `Subscriber`. publicvar output: [Output] { get }
/// The completion which will be sent to a `Subscriber`. publicvar completion: Subscribers.Completion<Failure> { get }
/// Set up a recording in a state ready to receive output. publicinit()
/// Set up a complete recording with the specified output and completion. publicinit(output: [Output], completion: Subscribers.Completion<Failure> = .finished)
/// Add an output to the recording. /// /// A `fatalError` will be raised if output is added after adding completion. publicmutatingfuncreceive(_ input: Record<Output, Failure>.Recording.Input)
/// Add a completion to the recording. /// /// A `fatalError` will be raised if more than one completion is added. publicmutatingfuncreceive(completion: Subscribers.Completion<Failure>) } }
/// A publisher that shares the output of an upstream publisher with multiple subscribers. /// /// This publisher type supports multiple subscribers, all of whom receive unchanged elements and completion states from the upstream publisher. /// /// > Tip: ``Publishers/Share`` is effectively a combination of the ``Publishers/Multicast`` and ``PassthroughSubject`` publishers, with an implicit ``ConnectablePublisher/autoconnect()``. /// /// Be aware that ``Publishers/Share`` is a class rather than a structure like most other publishers. Use this type when you need a publisher instance that uses reference semantics. finalpublicclassShare<Upstream> : Publisher, EquatablewhereUpstream : Publisher{
/// The kind of values published by this publisher. /// /// This publisher uses its upstream publisher's output type. publictypealiasOutput = Upstream.Output
/// The kind of errors this publisher might publish. /// /// This publisher uses its upstream publisher's failure type. publictypealiasFailure = Upstream.Failure
/// The publisher from which this publisher receives elements. finalpubliclet upstream: Upstream
/// Creates a publisher that shares the output of an upstream publisher with multiple subscribers. /// - Parameter upstream: The publisher from which this publisher receives elements. publicinit(upstream: Upstream)
/// Attaches the specified subscriber to this publisher. /// /// Implementations of ``Publisher`` must implement this method. /// /// The provided implementation of ``Publisher/subscribe(_:)-4u8kn``calls this method. /// /// - Parameter subscriber: The subscriber to attach to this ``Publisher``, after which it can receive values. finalpublicfuncreceive<S>(subscriber: S)whereS : Subscriber, Upstream.Failure == S.Failure, Upstream.Output == S.Input
/// Returns a Boolean value that indicates whether two publishers are equivalent. /// - Parameters: /// - lhs: A `Share` publisher to compare for equality. /// - rhs: Another `Share` publisher to compare for equality. /// - Returns: `true` if the publishers have reference equality (`===`); otherwise `false`. publicstaticfunc == (lhs: Publishers.Share<Upstream>, rhs: Publishers.Share<Upstream>) -> Bool }
/// A publisher that uses a subject to deliver elements to multiple subscribers. /// /// Use a multicast publisher when you have multiple downstream subscribers, but you want upstream publishers to only process one ``Subscriber/receive(_:)`` call per event. finalpublicclassMulticast<Upstream, SubjectType> : ConnectablePublisherwhereUpstream : Publisher, SubjectType : Subject, Upstream.Failure == SubjectType.Failure, Upstream.Output == SubjectType.Output{
/// The kind of values published by this publisher. /// /// This publisher uses its upstream publisher's output type. publictypealiasOutput = Upstream.Output
/// The kind of errors this publisher might publish. /// /// This publisher uses its upstream publisher's failure type. publictypealiasFailure = Upstream.Failure
/// The publisher from which this publisher receives its elements. finalpubliclet upstream: Upstream
/// A closure that returns a subject each time a subscriber attaches to the multicast publisher. finalpubliclet createSubject: () -> SubjectType
/// Creates a multicast publisher that applies a closure to create a subject that delivers elements to subscribers. /// /// - Parameter createSubject: A closure that returns a ``Subject`` each time a subscriber attaches to the multicast publisher. publicinit(upstream: Upstream, createSubject: @escaping () -> SubjectType)
/// Attaches the specified subscriber to this publisher. /// /// Implementations of ``Publisher`` must implement this method. /// /// The provided implementation of ``Publisher/subscribe(_:)-4u8kn``calls this method. /// /// - Parameter subscriber: The subscriber to attach to this ``Publisher``, after which it can receive values. finalpublicfuncreceive<S>(subscriber: S)whereS : Subscriber, SubjectType.Failure == S.Failure, SubjectType.Output == S.Input
/// Connects to the publisher, allowing it to produce elements, and returns an instance with which to cancel publishing. /// /// - Returns: A ``Cancellable`` instance that you use to cancel publishing. finalpublicfuncconnect() -> Cancellable }
Customize handling of asynchronous events by combining event-processing operators.
The Combine framework provides a declarative Swift API for processing values over time. These values can represent many kinds of asynchronous events. Combine declares publishers to expose values that can change over time, and subscribers to receive those vlaues from the publishers.
A unified, declarative API for processing values over time
Callbacks
Closures
Notifications
Key Value Observing
Features
Generic
Type safe
Composition first
Request driven
Back pressure
Combine is designed such that the subscriber controls the flow data, and because of that it also controls what and when processing happens in the pipeline. This is a feature of Combine called back-pressure.
This means that the subscriber drives the processing within a pipeline by providing information about how much information it wants or can accept. When a subscriber is connected to a publisher, it requests data based on a specific Demand.
The demand request is propagated up through the composed pipeline. Each operator in turn accepts the request for data and in turn requests information from the publishers to which it is connected.
1 2 3 4 5 6 7
In the first releaseof the Combine framework - in iOS 13priorto iOS 13.3and macOS priorto10.15.2 - when the subscriber requested datawith a Demand, that call itself was asynchronous.
Because this process acted as the driver which triggered attached operators and ultimately the source publisher, it meant that there were scenarios wheredata might appear to be lost.
Due to this, in iOS 13.3and later Combine releases, the process of requesting demand has been updatedto a synchronous/blocking call.
In practice, this means that you can be a bit more certain ofhavingany pipelines created and fully engaged priorto a publisher receiving the request to send anydata.
With the subscriber driving this process, it allows Combine to support cancellation. Subscribers all conform to the Cancellabele protocol. This means they all have a function cancel() that can be invoked to terminate a pipeline and stop all realted processing.
Lifecycle of Publishers and Subscribers
When the subscriber is attached to a publisher, it starts with a call to .subscribe(_: Subscriber).
The publisher in turn acknowledges the subscription calling receive(subscription: Subscription).
After the subscription has been acknowledged, the subscriber requests N values with request(_: Demaind).
The publisher may then (as it has values) send N(or fewer) values using receive(_: Input). A publisher should never send more than the demand requested.
Any time after the subscription has been acknowledged, the subscriber may send a cancellation with .cancel().
A publisher may optionally send completion: receive(completion:). A completion can be either a normal termination, or may be a .failure completion, optionally propagating an error type. A pipeline that has been cancelled will not send any completions.
Key Concepts
Publisher
The Publisher protocol declares a type that can deliver a sequence of values over time. Publishers have operators to act on the values received from upstream publishers and republish them.
/// The kind of values published by this publisher. associatedtype Output
/// The kind of errors this publisher might publish. /// /// Use `Never` if this `Publisher` does not publish errors. associatedtype Failure : Error
/// Attaches the specified subscriber to this publisher. /// /// Implementations of ``Publisher`` must implement this method. /// /// The provided implementation of ``Publisher/subscribe(_:)-4u8kn``calls this method. /// /// - Parameter subscriber: The subscriber to attach to this ``Publisher``, after which it can receive values. funcreceive<S>(subscriber: S)whereS : Subscriber, Self.Failure == S.Failure, Self.Output == S.Input }
Recipe for an event stream
finite: could complete, e.g. network request
infinite: failure or finish will never happen, e.g. button click
Operators describe new publishers from existing
Strongly typed values/errors over time
Can be synchronous or asynchronous
Can attach compatible Subscribers
Subscriber
At the end of a chain of publishers, a Subscriber acts on elements as it receives them. Publishers only emit values when explicitly requested to do so by subscribers. This puts your subscriber code in control of how fast it receives events from the publishers it’s connected to.
// once funcreceive(subscription: Subscription) // zero or More values funcreceive(_ input: Input) -> Subscribers.Demaind // At most one completion funcreceive(completion: Subscribers.Completion<Failure>) }
Receives values and a completion
Reference type
The Pattern
Subscriber is attached to Publisher
Publisher sends a Subscription
Subscriber requests N values
Publisher sends N values or less
Publisher sends completion
Kinds of Subscribers
Key Path Assignment
1 2 3 4
let trickNamePublisher = ... // Publisher of <String, Never> let canceller = trickNamePublisher.assign(to: \.someProperty, on: someObject) // ... canceller.cancel()
Sinks
1 2 3 4 5
let trickNamePublisher = ... // Publisher of <String, Never>
let canceller = trickNamePublisher.sink { trickName in // Do something with trickName }
an object that acts both like a subscriber and a publisher. Operators are classes that adopt both the Subscriber protocol and Publisher protocol. They support subscribing to a publisher, and sending resutls to any subscribers.
/// A publisher that exposes a method for outside callers to publish elements. /// /// A subject is a publisher that you can use to ”inject” values into a stream, by calling its ``Subject/send(_:)`` method. This can be useful for adapting existing imperative code to the Combine model. @available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) publicprotocolSubject : AnyObject, Publisher{
/// Sends a value to the subscriber. /// /// - Parameter value: The value to send. funcsend(_ value: Self.Output)
/// Sends a completion signal to the subscriber. /// /// - Parameter completion: A `Completion` instance which indicates whether publishing has finished normally or failed with an error. funcsend(completion: Subscribers.Completion<Self.Failure>)
/// Sends a subscription to the subscriber. /// /// This call provides the ``Subject`` an opportunity to establish demand for any new upstream subscriptions. /// /// - Parameter subscription: The subscription instance through which the subscriber can request elements. funcsend(subscription: Subscription) }
/// A subject that broadcasts elements to downstream subscribers. /// /// As a concrete implementation of ``Subject``, the ``PassthroughSubject`` provides a convenient way to adapt existing imperative code to the Combine model. /// /// Unlike ``CurrentValueSubject``, a ``PassthroughSubject`` doesn’t have an initial value or a buffer of the most recently-published element. /// A ``PassthroughSubject`` drops values if there are no subscribers, or its current demand is zero. @available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) finalpublicclassPassthroughSubject<Output, Failure> : SubjectwhereFailure : Error{
publicinit()
/// Sends a subscription to the subscriber. /// /// This call provides the ``Subject`` an opportunity to establish demand for any new upstream subscriptions. /// /// - Parameter subscription: The subscription instance through which the subscriber can request elements. finalpublicfuncsend(subscription: Subscription)
/// Attaches the specified subscriber to this publisher. /// /// Implementations of ``Publisher`` must implement this method. /// /// The provided implementation of ``Publisher/subscribe(_:)-4u8kn``calls this method. /// /// - Parameter subscriber: The subscriber to attach to this ``Publisher``, after which it can receive values. finalpublicfuncreceive<S>(subscriber: S)whereOutput == S.Input, Failure == S.Failure, S : Subscriber
/// Sends a value to the subscriber. /// /// - Parameter value: The value to send. finalpublicfuncsend(_ input: Output)
/// Sends a completion signal to the subscriber. /// /// - Parameter completion: A `Completion` instance which indicates whether publishing has finished normally or failed with an error. finalpublicfuncsend(completion: Subscribers.Completion<Failure>) }
/// A subject that wraps a single value and publishes a new element whenever the value changes. /// /// Unlike ``PassthroughSubject``, ``CurrentValueSubject`` maintains a buffer of the most recently published element. /// /// Calling ``CurrentValueSubject/send(_:)`` on a ``CurrentValueSubject`` also updates the current value, making it equivalent to updating the ``CurrentValueSubject/value`` directly. @available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) finalpublicclassCurrentValueSubject<Output, Failure> : SubjectwhereFailure : Error{
/// The value wrapped by this subject, published as a new element whenever it changes. finalpublicvar value: Output
/// Creates a current value subject with the given initial value. /// /// - Parameter value: The initial value to publish. publicinit(_ value: Output)
/// Sends a subscription to the subscriber. /// /// This call provides the ``Subject`` an opportunity to establish demand for any new upstream subscriptions. /// /// - Parameter subscription: The subscription instance through which the subscriber can request elements. finalpublicfuncsend(subscription: Subscription)
/// Attaches the specified subscriber to this publisher. /// /// Implementations of ``Publisher`` must implement this method. /// /// The provided implementation of ``Publisher/subscribe(_:)-4u8kn``calls this method. /// /// - Parameter subscriber: The subscriber to attach to this ``Publisher``, after which it can receive values. finalpublicfuncreceive<S>(subscriber: S)whereOutput == S.Input, Failure == S.Failure, S : Subscriber
/// Sends a value to the subscriber. /// /// - Parameter value: The value to send. finalpublicfuncsend(_ input: Output)
/// Sends a completion signal to the subscriber. /// /// - Parameter completion: A `Completion` instance which indicates whether publishing has finished normally or failed with an error. finalpublicfuncsend(completion: Subscribers.Completion<Failure>) }
/// A protocol that defines when and how to execute a closure. /// /// You can use a scheduler to execute code as soon as possible, or after a future date. /// Individual scheduler implementations use whatever time-keeping system makes sense for them. Schedulers express this as their `SchedulerTimeType`. Since this type conforms to ``SchedulerTimeIntervalConvertible``, you can always express these times with the convenience functions like `.milliseconds(500)`. Schedulers can accept options to control how they execute the actions passed to them. These options may control factors like which threads or dispatch queues execute the actions. @available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) publicprotocolScheduler{
/// Describes an instant in time for this scheduler. associatedtype SchedulerTimeType : StrideablewhereSelf.SchedulerTimeType.Stride : SchedulerTimeIntervalConvertible
/// A type that defines options accepted by the scheduler. /// /// This type is freely definable by each `Scheduler`. Typically, operations that take a `Scheduler` parameter will also take `SchedulerOptions`. associatedtype SchedulerOptions
/// This scheduler’s definition of the current moment in time. var now: Self.SchedulerTimeType { get }
/// The minimum tolerance allowed by the scheduler. var minimumTolerance: Self.SchedulerTimeType.Stride { get }
/// Performs the action at the next possible opportunity. funcschedule(options: Self.SchedulerOptions?, _ action: @escaping () -> Void)
/// Performs the action at some time after the specified date. funcschedule(after date: Self.SchedulerTimeType, tolerance: Self.SchedulerTimeType.Stride, options: Self.SchedulerOptions?, _ action: @escaping () -> Void)
/// Performs the action at some time after the specified date, at the specified frequency, optionally taking into account tolerance if possible. funcschedule(after date: Self.SchedulerTimeType, interval: Self.SchedulerTimeType.Stride, tolerance: Self.SchedulerTimeType.Stride, options: Self.SchedulerOptions?, _ action: @escaping () -> Void) -> Cancellable }
/// Specifies the scheduler on which to receive elements from the publisher. /// /// You use the ``Publisher/receive(on:options:)`` operator to receive results and completion on a specific scheduler, such as performing UI work on the main run loop. In contrast with ``Publisher/subscribe(on:options:)``, which affects upstream messages, ``Publisher/receive(on:options:)`` changes the execution context of downstream messages. /// /// In the following example, the ``Publisher/subscribe(on:options:)`` operator causes `jsonPublisher` to receive requests on `backgroundQueue`, while the /// ``Publisher/receive(on:options:)`` causes `labelUpdater` to receive elements and completion on `RunLoop.main`. /// /// let jsonPublisher = MyJSONLoaderPublisher() // Some publisher. /// let labelUpdater = MyLabelUpdateSubscriber() // Some subscriber that updates the UI. /// /// jsonPublisher /// .subscribe(on: backgroundQueue) /// .receive(on: RunLoop.main) /// .subscribe(labelUpdater) /// /// /// Prefer ``Publisher/receive(on:options:)`` over explicit use of dispatch queues when performing work in subscribers. For example, instead of the following pattern: /// /// pub.sink { /// DispatchQueue.main.async { /// // Do something. /// } /// } /// /// Use this pattern instead: /// /// pub.receive(on: DispatchQueue.main).sink { /// // Do something. /// } /// /// > Note: ``Publisher/receive(on:options:)`` doesn’t affect the scheduler used to call the subscriber’s ``Subscriber/receive(subscription:)`` method. /// /// - Parameters: /// - scheduler: The scheduler the publisher uses for element delivery. /// - options: Scheduler options used to customize element delivery. /// - Returns: A publisher that delivers elements using the specified scheduler. publicfuncreceive<S>(on scheduler: S, options: S.SchedulerOptions? = nil) -> Publishers.ReceiveOn<Self, S> whereS : Scheduler }
ContiguousArray<Element> is the fastest and simplest of the three(ContiguousArray, Array, ArraySlice) – use this when you need “C array” performance. The elements of a ContiguousArray are always stored contiguously in memory.
The ContiguousArray type is a specialized array that always stores its elements in a contiguous region of memory. This contrasts with Array, which can store its elements in either a contiguous region of memory or an NSArray instance if its Element type is a class or @objc protocol.
If your array’s Element type is a class or @objc protocol and you do not need to bridge the array to NSArray or pass the array to Objective-C APIs, using ContiguousArray may be more efficient and have more predictable performance than Array.
If the array’s Element type is a struct or enumeration, Array and ContiguousArray should have similar efficiency.
/// Initialization from an existing buffer does not have "array.init" /// semantics because the caller may retain an alias to buffer. @inlinable internalinit(_buffer: _Buffer) { self._buffer = _buffer } }
// __ContiguousArrayStorageBase supplies the implementation of the // _NSArrayCore API (and thus, NSArray the API) for our // _ContiguousArrayStorage. We can’t put this implementation // directly on _ContiguousArrayStorage because generic classes can’t // override Objective-C selectors. //
/// Base class of the heap buffer backing arrays. /// /// NOTE: older runtimes called this _ContiguousArrayStorageBase. The /// two must coexist, so it was renamed. The old name must not be used /// in the new runtime. // 大部分方法需要子类实现 @usableFromInline @_fixed_layout internalclass__ContiguousArrayStorageBase: __SwiftNativeNSArrayWithContiguousStorage{ @Usablefrominline finalvar countAndCapacity: _ArrayBody
@inlinable @nonobjc internalinit(_doNotCallMeBase: ()) { _internalInvariantFailure("creating instance of __ContiguousArrayStorageBase") } #if _runtime(_ObjC) internaloverridefuncwithUnsafeBufferOfObjects<R>( _ body: (UnsafeBufferPointer<AnyObject>)throws -> R ) rethrows -> R { iflet result = try _withVerbatimBridgedUnsafeBuffer(body) { return result } _internalInvariantFailure( "Can't use a buffer of non-verbatim-bridged elements as an NSArray") }
/// If the stored type is bridged verbatim, invoke `body` on an /// `UnsafeBufferPointer` to the elements and return the result. /// Otherwise, return `nil`. internalfunc_withVerbatimBridgedUnsafeBuffer<R>( _ body: (UnsafeBufferPointer<AnyObject>)throws -> R ) rethrows -> R? { _internalInvariantFailure( "Concrete subclasses must implement _withVerbatimBridgedUnsafeBuffer") }
/// A type that every element in the array is. @inlinable internalvar staticElementType: Any.Type { _internalInvariantFailure( "Concrete subclasses must implement staticElementType") } @inlinable deinit { _internalInvariant( self !== _emptyArrayStorage, "Deallocating empty array storage?!") } }
/// Make a buffer with uninitialized elements. After using this /// method, you must either initialize the `count` elements at the /// result's `.firstElementAddress` or set the result's `.count` /// to zero. @inlinable internalinit( _uninitializedCount uninitializedCount: Int, minimumCapacity: Int ) { let realMinimumCapacity = Swift.max(uninitializedCount, minimumCapacity) if realMinimumCapacity == 0 { self = _ContiguousArrayBuffer<Element>() } else { // 初始化一个`_ContiguousArrayStorage<Element>`的实例, // 并在后面申请`realMinimumCapacity`大小的连续内存 // 然后更新StorageHeader _storage = Builtin.allocWithTailElems_1( getContiguousArrayStorageType(for: Element.self), realMinimumCapacity._builtinWordValue, Element.self)
/// Initialize the body part of our storage. /// /// - Warning: does not initialize elements @inlinable internalfunc_initStorageHeader(count: Int, capacity: Int) { #if _runtime(_ObjC) let verbatim = _isBridgedVerbatimToObjectiveC(Element.self) #else let verbatim = false #endif // 赋值`_storage`中的`countAndCapacity` // We can initialize by assignment because _ArrayBody is a trivial type, // i.e. contains no references. _storage.countAndCapacity = _ArrayBody( count: count, capacity: capacity, elementTypeIsBridgedVerbatim: verbatim) }
/// An `NSArray` with Swift-native reference counting and contiguous /// storage. /// /// NOTE: older runtimes called this /// _SwiftNativeNSArrayWithContiguousStorage. The two must coexist, so /// it was renamed. The old name must not be used in the new runtime. @_fixed_layout @usableFromInline internalclass__SwiftNativeNSArrayWithContiguousStorage : __SwiftNativeNSArray{ // Provides NSArray inheritance and native refcounting
/// Adds a new element at the end of the array. /// /// Use this method to append a single element to the end of a mutable array. /// /// var numbers = [1, 2, 3, 4, 5] /// numbers.append(100) /// print(numbers) /// // Prints "[1, 2, 3, 4, 5, 100]" /// /// Because arrays increase their allocated capacity using an exponential /// strategy, appending a single element to an array is an O(1) operation /// when averaged over many calls to the `append(_:)` method. When an array /// has additional capacity and is not sharing its storage with another /// instance, appending an element is O(1). When an array needs to /// reallocate storage before appending or its storage is shared with /// another copy, appending is O(*n*), where *n* is the length of the array. /// /// - Parameter newElement: The element to append to the array. /// /// - Complexity: O(1) on average, over many calls to `append(_:)` on the /// same array. @inlinable @_semantics("array.append_element") publicmutatingfuncappend(_ newElement: __owned Element) { // Separating uniqueness check and capacity check allows hoisting the // uniqueness check out of a loop. _makeUniqueAndReserveCapacityIfNotUnique() let oldCount = _buffer.mutableCount _reserveCapacityAssumingUniqueBuffer(oldCount: oldCount) _appendElementAssumeUniqueAndCapacity(oldCount, newElement: newElement) _endMutation() }
/// Creates a new buffer, replacing the current buffer. /// /// If `bufferIsUnique` is true, the buffer is assumed to be uniquely /// referenced by this array and the elements are moved - instead of copied - /// to the new buffer. /// The `minimumCapacity` is the lower bound for the new capacity. /// If `growForAppend` is true, the new capacity is calculated using /// `_growArrayCapacity`. @_alwaysEmitIntoClient @inline(never) internalmutatingfunc_createNewBuffer( bufferIsUnique: Bool, minimumCapacity: Int, growForAppend: Bool ) { _internalInvariant(!bufferIsUnique || _buffer.isUniquelyReferenced()) _buffer = _buffer._consumeAndCreateNew(bufferIsUnique: bufferIsUnique, minimumCapacity: minimumCapacity, growForAppend: growForAppend) }
/// Creates and returns a new uniquely referenced buffer which is a copy of /// this buffer. /// /// If `bufferIsUnique` is true, the buffer is assumed to be uniquely /// referenced and the elements are moved - instead of copied - to the new /// buffer. /// The `minimumCapacity` is the lower bound for the new capacity. /// If `growForAppend` is true, the new capacity is calculated using /// `_growArrayCapacity`, but at least kept at `minimumCapacity`. /// /// This buffer is consumed, i.e. it's released. @_alwaysEmitIntoClient @inline(never) @_semantics("optimize.sil.specialize.owned2guarantee.never") internal __consuming func_consumeAndCreateNew( bufferIsUnique: Bool, minimumCapacity: Int, growForAppend: Bool ) -> _ArrayBuffer { let newCapacity = _growArrayCapacity(oldCapacity: capacity, minimumCapacity: minimumCapacity, growForAppend: growForAppend) letc = count _internalInvariant(newCapacity >= c) let newBuffer = _ContiguousArrayBuffer<Element>( _uninitializedCount: c, minimumCapacity: newCapacity)
/// 当buffer is Unique, 直接不进行copy,操作数据 if bufferIsUnique { // As an optimization, if the original buffer is unique, we can just move // the elements instead of copying. let dest = newBuffer.firstElementAddress dest.moveInitialize(from: mutableFirstElementAddress, count: c) _native.mutableCount = 0 } else { /// 进行复制 _copyContents( subRange: 0..<c, initializing: newBuffer.mutableFirstElementAddress) } return _ArrayBuffer(_buffer: newBuffer, shiftedToStartIndex: 0) }
Collection extends Sequence. It guarantees that the sequence is multi-pass, and it allows you to look up elements by their indices. It also adds slicing capabilities via its SubSequence type, which is a collection itself.
/// A type that iterates over a collection using its indices. /// /// The `IndexingIterator` type is the default iterator for any collection that /// doesn't declare its own. It acts as an iterator by using a collection's /// indices to step over each value in the collection. Most collections in the /// standard library use `IndexingIterator` as their iterator. /// /// By default, any custom collection type you create will inherit a /// `makeIterator()` method that returns an `IndexingIterator` instance, /// making it unnecessary to declare your own. When creating a custom /// collection type, add the minimal requirements of the `Collection` /// protocol: starting and ending indices and a subscript for accessing /// elements. With those elements defined, the inherited `makeIterator()` /// method satisfies the requirements of the `Sequence` protocol. /// /// Here's an example of a type that declares the minimal requirements for a /// collection. The `CollectionOfTwo` structure is a fixed-size collection /// that always holds two elements of a specific type. /// /// struct CollectionOfTwo<Element>: Collection { /// let elements: (Element, Element) /// /// init(_ first: Element, _ second: Element) { /// self.elements = (first, second) /// } /// /// var startIndex: Int { return 0 } /// var endIndex: Int { return 2 } /// /// subscript(index: Int) -> Element { /// switch index { /// case 0: return elements.0 /// case 1: return elements.1 /// default: fatalError("Index out of bounds.") /// } /// } /// /// func index(after i: Int) -> Int { /// precondition(i < endIndex, "Can't advance beyond endIndex") /// return i + 1 /// } /// } /// /// Because `CollectionOfTwo` doesn't define its own `makeIterator()` /// method or `Iterator` associated type, it uses the default iterator type, /// `IndexingIterator`. This example shows how a `CollectionOfTwo` instance /// can be created holding the values of a point, and then iterated over /// using a `for`-`in` loop. /// /// let point = CollectionOfTwo(15.0, 20.0) /// for element in point { /// print(element) /// } /// // Prints "15.0" /// // Prints "20.0" @frozen publicstructIndexingIterator<Elements: Collection> { @usableFromInline internallet _elements: Elements @usableFromInline internalvar _position: Elements.Index
/// Creates an iterator over the given collection. @inlinable @inline(__always) public/// @testable init(_elements: Elements) { self._elements = _elements self._position = _elements.startIndex }
/// Creates an iterator over the given collection. @inlinable @inline(__always) public/// @testable init(_elements: Elements, _position: Elements.Index) { self._elements = _elements self._position = _position } }
/// Advances to the next element and returns it, or `nil` if no next element /// exists. /// /// Repeatedly calling this method returns all the elements of the underlying /// sequence in order. As soon as the sequence has run out of elements, all /// subsequent calls return `nil`. /// /// This example shows how an iterator can be used explicitly to emulate a /// `for`-`in` loop. First, retrieve a sequence's iterator, and then call /// the iterator's `next()` method until it returns `nil`. /// /// let numbers = [2, 3, 5, 7] /// var numbersIterator = numbers.makeIterator() /// /// while let num = numbersIterator.next() { /// print(num) /// } /// // Prints "2" /// // Prints "3" /// // Prints "5" /// // Prints "7" /// /// - Returns: The next element in the underlying sequence if a next element /// exists; otherwise, `nil`. @inlinable @inline(__always) publicmutatingfuncnext() -> Elements.Element? { if _position == _elements.endIndex { returnnil } let element = _elements[_position] _elements.formIndex(after: &_position) return element } }
publicprotocolCollection: Sequence{ // FIXME: ideally this would be in MigrationSupport.swift, but it needs // to be on the protocol instead of as an extension @available(*, deprecated/*, obsoleted: 5.0*/, message: "all index distances are now of type Int") typealiasIndexDistance = Int
// FIXME: Associated type inference requires this. override associatedtype Element
// FIXME: <rdar://problem/34142121> // This typealias should be removed as it predates the source compatibility // guarantees of Swift 3, but it cannot due to a bug. @available(swift, deprecated: 3.2, obsoleted: 5.0, renamed: "Element") typealias _Element = Element
/// A type that represents a position in the collection. /// /// Valid indices consist of the position of every element and a /// "past the end" position that's not valid for use as a subscript /// argument. associatedtype Index: Comparable
/// The position of the first element in a nonempty collection. /// /// If the collection is empty, `startIndex` is equal to `endIndex`. var startIndex: Index { get } /// The collection's "past the end" position---that is, the position one /// greater than the last valid subscript argument. /// /// When you need a range that includes the last element of a collection, use /// the half-open range operator (`..<`) with `endIndex`. The `..<` operator /// creates a range that doesn't include the upper bound, so it's always /// safe to use with `endIndex`. For example: /// /// let numbers = [10, 20, 30, 40, 50] /// if let index = numbers.firstIndex(of: 30) { /// print(numbers[index ..< numbers.endIndex]) /// } /// // Prints "[30, 40, 50]" /// /// If the collection is empty, `endIndex` is equal to `startIndex`. var endIndex: Index { get }
/// A type that provides the collection's iteration interface and /// encapsulates its iteration state. /// /// By default, a collection conforms to the `Sequence` protocol by /// supplying `IndexingIterator` as its associated `Iterator` /// type. associatedtype Iterator = IndexingIterator<Self>
// FIXME: Only needed for associated type inference. Otherwise, // we get an `IndexingIterator` rather than properly deducing the // Iterator type from makeIterator(). <rdar://problem/21539115> /// Returns an iterator over the elements of the collection. override __consuming funcmakeIterator() -> Iterator
/// A collection representing a contiguous subrange of this collection's /// elements. The subsequence shares indices with the original collection. /// /// The default subsequence type for collections that don't define their own /// is `Slice`. associatedtype SubSequence: Collection = Slice<Self> whereSubSequence.Index == Index, Element == SubSequence.Element, SubSequence.SubSequence == SubSequence
/// Accesses the element at the specified position. /// /// The following example accesses an element of an array through its /// subscript to print its value: /// /// var streets = ["Adams", "Bryant", "Channing", "Douglas", "Evarts"] /// print(streets[1]) /// // Prints "Bryant" /// /// You can subscript a collection with any valid index other than the /// collection's end index. The end index refers to the position one past /// the last element of a collection, so it doesn't correspond with an /// element. /// /// - Parameter position: The position of the element to access. `position` /// must be a valid index of the collection that is not equal to the /// `endIndex` property. /// /// - Complexity: O(1) @_borrowed subscript(position: Index) -> Element { get }
/// Accesses a contiguous subrange of the collection's elements. /// /// For example, using a `PartialRangeFrom` range expression with an array /// accesses the subrange from the start of the range expression until the /// end of the array. /// /// let streets = ["Adams", "Bryant", "Channing", "Douglas", "Evarts"] /// let streetsSlice = streets[2..<5] /// print(streetsSlice) /// // ["Channing", "Douglas", "Evarts"] /// /// The accessed slice uses the same indices for the same elements as the /// original collection. This example searches `streetsSlice` for one of the /// strings in the slice, and then uses that index in the original array. /// /// let index = streetsSlice.firstIndex(of: "Evarts")! // 4 /// print(streets[index]) /// // "Evarts" /// /// Always use the slice's `startIndex` property instead of assuming that its /// indices start at a particular value. Attempting to access an element by /// using an index outside the bounds of the slice may result in a runtime /// error, even if that index is valid for the original collection. /// /// print(streetsSlice.startIndex) /// // 2 /// print(streetsSlice[2]) /// // "Channing" /// /// print(streetsSlice[0]) /// // error: Index out of bounds /// /// - Parameter bounds: A range of the collection's indices. The bounds of /// the range must be valid indices of the collection. /// /// - Complexity: O(1) subscript(bounds: Range<Index>) -> SubSequence { get }
/// A type that represents the indices that are valid for subscripting the /// collection, in ascending order. associatedtype Indices: Collection = DefaultIndices<Self> whereIndices.Element == Index, Indices.Index == Index, Indices.SubSequence == Indices /// The indices that are valid for subscripting the collection, in ascending /// order. /// /// A collection's `indices` property can hold a strong reference to the /// collection itself, causing the collection to be nonuniquely referenced. /// If you mutate the collection while iterating over its indices, a strong /// reference can result in an unexpected copy of the collection. To avoid /// the unexpected copy, use the `index(after:)` method starting with /// `startIndex` to produce indices instead. /// /// var c = MyFancyCollection([10, 20, 30, 40, 50]) /// var i = c.startIndex /// while i != c.endIndex { /// c[i] /= 5 /// i = c.index(after: i) /// } /// // c == MyFancyCollection([2, 4, 6, 8, 10]) varindices: Indices { get }
/// A Boolean value indicating whether the collection is empty. /// /// When you need to check whether your collection is empty, use the /// `isEmpty` property instead of checking that the `count` property is /// equal to zero. For collections that don't conform to /// `RandomAccessCollection`, accessing the `count` property iterates /// through the elements of the collection. /// /// let horseName = "Silver" /// if horseName.isEmpty { /// print("My horse has no name.") /// } else { /// print("Hi ho, \(horseName)!") /// } /// // Prints "Hi ho, Silver!" /// /// - Complexity: O(1) var isEmpty: Bool { get }
/// The number of elements in the collection. /// /// To check whether a collection is empty, use its `isEmpty` property /// instead of comparing `count` to zero. Unless the collection guarantees /// random-access performance, calculating `count` can be an O(*n*) /// operation. /// /// - Complexity: O(1) if the collection conforms to /// `RandomAccessCollection`; otherwise, O(*n*), where *n* is the length /// of the collection. varcount: Int { get } // The following requirements enable dispatching for firstIndex(of:) and // lastIndex(of:) when the element type is Equatable.
/// Returns `Optional(Optional(index))` if an element was found /// or `Optional(nil)` if an element was determined to be missing; /// otherwise, `nil`. /// /// - Complexity: O(*n*), where *n* is the length of the collection. func_customIndexOfEquatableElement(_ element: Element) -> Index??
/// Customization point for `Collection.lastIndex(of:)`. /// /// Define this method if the collection can find an element in less than /// O(*n*) by exploiting collection-specific knowledge. /// /// - Returns: `nil` if a linear search should be attempted instead, /// `Optional(nil)` if the element was not found, or /// `Optional(Optional(index))` if an element was found. /// /// - Complexity: Hopefully less than O(`count`). func_customLastIndexOfEquatableElement(_ element: Element) -> Index??
/// Returns an index that is the specified distance from the given index. /// /// The following example obtains an index advanced four positions from a /// string's starting index and then prints the character at that position. /// /// let s = "Swift" /// let i = s.index(s.startIndex, offsetBy: 4) /// print(s[i]) /// // Prints "t" /// /// The value passed as `distance` must not offset `i` beyond the bounds of /// the collection. /// /// - Parameters: /// - i: A valid index of the collection. /// - distance: The distance to offset `i`. `distance` must not be negative /// unless the collection conforms to the `BidirectionalCollection` /// protocol. /// - Returns: An index offset by `distance` from the index `i`. If /// `distance` is positive, this is the same value as the result of /// `distance` calls to `index(after:)`. If `distance` is negative, this /// is the same value as the result of `abs(distance)` calls to /// `index(before:)`. /// /// - Complexity: O(1) if the collection conforms to /// `RandomAccessCollection`; otherwise, O(*k*), where *k* is the absolute /// value of `distance`. funcindex(_ i: Index, offsetBy distance: Int) -> Index
/// Returns an index that is the specified distance from the given index, /// unless that distance is beyond a given limiting index. /// /// The following example obtains an index advanced four positions from a /// string's starting index and then prints the character at that position. /// The operation doesn't require going beyond the limiting `s.endIndex` /// value, so it succeeds. /// /// let s = "Swift" /// if let i = s.index(s.startIndex, offsetBy: 4, limitedBy: s.endIndex) { /// print(s[i]) /// } /// // Prints "t" /// /// The next example attempts to retrieve an index six positions from /// `s.startIndex` but fails, because that distance is beyond the index /// passed as `limit`. /// /// let j = s.index(s.startIndex, offsetBy: 6, limitedBy: s.endIndex) /// print(j) /// // Prints "nil" /// /// The value passed as `distance` must not offset `i` beyond the bounds of /// the collection, unless the index passed as `limit` prevents offsetting /// beyond those bounds. /// /// - Parameters: /// - i: A valid index of the collection. /// - distance: The distance to offset `i`. `distance` must not be negative /// unless the collection conforms to the `BidirectionalCollection` /// protocol. /// - limit: A valid index of the collection to use as a limit. If /// `distance > 0`, a limit that is less than `i` has no effect. /// Likewise, if `distance < 0`, a limit that is greater than `i` has no /// effect. /// - Returns: An index offset by `distance` from the index `i`, unless that /// index would be beyond `limit` in the direction of movement. In that /// case, the method returns `nil`. /// /// - Complexity: O(1) if the collection conforms to /// `RandomAccessCollection`; otherwise, O(*k*), where *k* is the absolute /// value of `distance`. funcindex( _ i: Index, offsetBy distance: Int, limitedBy limit: Index ) -> Index?
/// Returns the distance between two indices. /// /// Unless the collection conforms to the `BidirectionalCollection` protocol, /// `start` must be less than or equal to `end`. /// /// - Parameters: /// - start: A valid index of the collection. /// - end: Another valid index of the collection. If `end` is equal to /// `start`, the result is zero. /// - Returns: The distance between `start` and `end`. The result can be /// negative only if the collection conforms to the /// `BidirectionalCollection` protocol. /// /// - Complexity: O(1) if the collection conforms to /// `RandomAccessCollection`; otherwise, O(*k*), where *k* is the /// resulting distance. funcdistance(from start: Index, to end: Index) -> Int
/// Performs a range check in O(1), or a no-op when a range check is not /// implementable in O(1). /// /// The range check, if performed, is equivalent to: /// /// precondition(bounds.contains(index)) /// /// Use this function to perform a cheap range check for QoI purposes when /// memory safety is not a concern. Do not rely on this range check for /// memory safety. /// /// The default implementation for forward and bidirectional indices is a /// no-op. The default implementation for random access indices performs a /// range check. /// /// - Complexity: O(1). func_failEarlyRangeCheck(_ index: Index, bounds: Range<Index>)
/// Performs a range check in O(1), or a no-op when a range check is not /// implementable in O(1). /// /// The range check, if performed, is equivalent to: /// /// precondition( /// bounds.contains(range.lowerBound) || /// range.lowerBound == bounds.upperBound) /// precondition( /// bounds.contains(range.upperBound) || /// range.upperBound == bounds.upperBound) /// /// Use this function to perform a cheap range check for QoI purposes when /// memory safety is not a concern. Do not rely on this range check for /// memory safety. /// /// The default implementation for forward and bidirectional indices is a /// no-op. The default implementation for random access indices performs a /// range check. /// /// - Complexity: O(1). func_failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>)
/// Returns the position immediately after the given index. /// /// The successor of an index must be well defined. For an index `i` into a /// collection `c`, calling `c.index(after: i)` returns the same index every /// time. /// /// - Parameter i: A valid index of the collection. `i` must be less than /// `endIndex`. /// - Returns: The index value immediately after `i`. funcindex(after i: Index) -> Index
/// Replaces the given index with its successor. /// /// - Parameter i: A valid index of the collection. `i` must be less than /// `endIndex`. funcformIndex(after i: inout Index) }
/// 这两个方法我觉得可以用在测试代码中,如可以方便的随机选取登陆用户账号密码用于测试,或者随机一个dataset传入要测试的方法中 @inlinable publicfuncrandomElement<T: RandomNumberGenerator>( using generator: inout T ) -> Element? { guard !isEmpty else { returnnil } let random = Int.random(in: 0 ..< count, using: &generator) let idx = index(startIndex, offsetBy: random) returnself[idx] } @inlinable publicfuncrandomElement() -> Element? { var g = SystemRandomNumberGenerator() return randomElement(using: &g) }
/// The system's default source of random data. /// /// When you generate random values, shuffle a collection, or perform another /// operation that depends on random data, this type is the generator used by /// default. For example, the two method calls in this example are equivalent: /// /// let x = Int.random(in: 1...100) /// var g = SystemRandomNumberGenerator() /// let y = Int.random(in: 1...100, using: &g) /// /// `SystemRandomNumberGenerator` is automatically seeded, is safe to use in /// multiple threads, and uses a cryptographically secure algorithm whenever /// possible. /// /// Platform Implementation of `SystemRandomNumberGenerator` /// ======================================================== /// /// While the system generator is automatically seeded and thread-safe on every /// platform, the cryptographic quality of the stream of random data produced by /// the generator may vary. For more detail, see the documentation for the APIs /// used by each platform. /// /// - Apple platforms use `arc4random_buf(3)`. /// - Linux platforms use `getrandom(2)` when available; otherwise, they read /// from `/dev/urandom`. /// - Windows uses `BCryptGenRandom` @frozen publicstructSystemRandomNumberGenerator: RandomNumberGenerator, Sendable{ /// Creates a new instance of the system's default random number generator. @inlinable publicinit() { }
/// Returns a value from a uniform, independent distribution of binary data. /// /// - Returns: An unsigned 64-bit random value. @inlinable publicmutatingfuncnext() -> UInt64 { var random: UInt64 = 0 swift_stdlib_random(&random, MemoryLayout<UInt64>.size) return random } }
popFirst
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/// Removes and returns the first element of the collection. /// /// - Returns: The first element of the collection if the collection is /// not empty; otherwise, `nil`. /// /// - Complexity: O(1) @inlinable publicmutatingfuncpopFirst() -> Element? { // TODO: swift-3-indexing-model - review the following guard !isEmpty else { returnnil } /// 一定有倔种来告诉我,我们在swift不推荐使用“!” let element = first! /// 你删除first这么带劲吗? self = self[index(after: startIndex)..<endIndex] return element }
/// isEmpty 有什么值得写的?请认真看看下面的注视 /// A Boolean value indicating whether the collection is empty. /// /// When you need to check whether your collection is empty, use the /// `isEmpty` property instead of checking that the `count` property is /// equal to zero. For collections that don't conform to /// `RandomAccessCollection`, accessing the `count` property iterates /// through the elements of the collection. /// /// let horseName = "Silver" /// if horseName.isEmpty { /// print("My horse has no name.") /// } else { /// print("Hi ho, \(horseName)!") /// } /// // Prints "Hi ho, Silver!") /// /// - Complexity: O(1) @inlinable publicvar isEmpty: Bool { return startIndex == endIndex }
Sequence provides iteration. It allows you to create an iterator, but there are no guarantees about whether the sequence is single-pass (e.g. reading from standard input) or multi-pass (iterating over an array).
publicprotocolIteratorProtocol{ /// The type of element traversed by the iterator. associatedtype Element
/// Advances to the next element and returns it, or `nil` if no next element /// exists. /// /// Repeatedly calling this method returns, in order, all the elements of the /// underlying sequence. As soon as the sequence has run out of elements, all /// subsequent calls return `nil`. /// /// You must not call this method if any other copy of this iterator has been /// advanced with a call to its `next()` method. /// /// The following example shows how an iterator can be used explicitly to /// emulate a `for`-`in` loop. First, retrieve a sequence's iterator, and /// then call the iterator's `next()` method until it returns `nil`. /// /// let numbers = [2, 3, 5, 7] /// var numbersIterator = numbers.makeIterator() /// /// while let num = numbersIterator.next() { /// print(num) /// } /// // Prints "2" /// // Prints "3" /// // Prints "5" /// // Prints "7" /// /// - Returns: The next element in the underlying sequence, if a next element /// exists; otherwise, `nil`. mutatingfuncnext() -> Element? }
publicprotocolSequence{ /// A type representing the sequence's elements. associatedtype Element
/// A type that provides the sequence's iteration interface and /// encapsulates its iteration state. associatedtype Iterator: IteratorProtocolwhereIterator.Element == Element
// FIXME: <rdar://problem/34142121> // This typealias should be removed as it predates the source compatibility // guarantees of Swift 3, but it cannot due to a bug. @available(*, unavailable, renamed: "Iterator") typealiasGenerator = Iterator
/// A type that represents a subsequence of some of the sequence's elements. // associatedtype SubSequence: Sequence = AnySequence<Element> // where Element == SubSequence.Element, // SubSequence.SubSequence == SubSequence // typealias SubSequence = AnySequence<Element>
/// Returns an iterator over the elements of this sequence. __consuming funcmakeIterator() -> Iterator
/// A value less than or equal to the number of elements in the sequence, /// calculated nondestructively. /// /// The default implementation returns 0. If you provide your own /// implementation, make sure to compute the value nondestructively. /// /// - Complexity: O(1), except if the sequence also conforms to `Collection`. /// In this case, see the documentation of `Collection.underestimatedCount`. var underestimatedCount: Int { get }
func_customContainsEquatableElement( _ element: Element ) -> Bool?
/// Create a native array buffer containing the elements of `self`, /// in the same order. __consuming func_copyToContiguousArray() -> ContiguousArray<Element>
/// Copy `self` into an unsafe buffer, initializing its memory. /// /// The default implementation simply iterates over the elements of the /// sequence, initializing the buffer one item at a time. /// /// For sequences whose elements are stored in contiguous chunks of memory, /// it may be more efficient to copy them in bulk, using the /// `UnsafeMutablePointer.initialize(from:count:)` method. /// /// - Parameter ptr: An unsafe buffer addressing uninitialized memory. The /// buffer must be of sufficient size to accommodate /// `source.underestimatedCount` elements. (Some implementations trap /// if given a buffer that's smaller than this.) /// /// - Returns: `(it, c)`, where `c` is the number of elements copied into the /// buffer, and `it` is a partially consumed iterator that can be used to /// retrieve elements that did not fit into the buffer (if any). (This can /// only happen if `underestimatedCount` turned out to be an actual /// underestimate, and the buffer did not contain enough space to hold the /// entire sequence.) /// /// On return, the memory region in `buffer[0 ..< c]` is initialized to /// the first `c` elements in the sequence. __consuming func_copyContents( initializing ptr: UnsafeMutableBufferPointer<Element> ) -> (Iterator,UnsafeMutableBufferPointer<Element>.Index)
/// Executes a closure on the sequence’s contiguous storage. /// /// This method calls `body(buffer)`, where `buffer` is a pointer to the /// collection’s contiguous storage. If the contiguous storage doesn't exist, /// the collection creates it. If the collection doesn’t support an internal /// representation in a form of contiguous storage, the method doesn’t call /// `body` --- it immediately returns `nil`. /// /// The optimizer can often eliminate bounds- and uniqueness-checking /// within an algorithm. When that fails, however, invoking the same /// algorithm on the `buffer` argument may let you trade safety for speed. /// /// Successive calls to this method may provide a different pointer on each /// call. Don't store `buffer` outside of this method. /// /// A `Collection` that provides its own implementation of this method /// must provide contiguous storage to its elements in the same order /// as they appear in the collection. This guarantees that it's possible to /// generate contiguous mutable storage to any of its subsequences by slicing /// `buffer` with a range formed from the distances to the subsequence's /// `startIndex` and `endIndex`, respectively. /// /// - Parameters: /// - body: A closure that receives an `UnsafeBufferPointer` to the /// sequence's contiguous storage. /// - Returns: The value returned from `body`, unless the sequence doesn't /// support contiguous storage, in which case the method ignores `body` and /// returns `nil`. funcwithContiguousStorageIfAvailable<R>( _ body: (_ buffer: UnsafeBufferPointer<Element>)throws -> R ) rethrows -> R? }
/// A sequence that lazily consumes and drops `n` elements from an underlying /// `Base` iterator before possibly returning the first available element. /// /// The underlying iterator's sequence may be infinite. @frozen publicstructDropFirstSequence<Base: Sequence> { @usableFromInline internallet _base: Base @usableFromInline internallet _limit: Int @inlinable publicinit(_ base: Base, dropping limit: Int) { _precondition(limit >= 0, "Can't drop a negative number of elements from a sequence") _base = base _limit = limit } }
extensionDropFirstSequence: Sequence{ publictypealiasElement = Base.Element publictypealiasIterator = Base.Iterator publictypealiasSubSequence = AnySequence<Element> @inlinable public __consuming funcmakeIterator() -> Iterator { var it = _base.makeIterator() var dropped = 0 while dropped < _limit, it.next() != nil { dropped &+= 1 } return it }
@inlinable public __consuming funcdropFirst(_ k: Int) -> DropFirstSequence<Base> { // If this is already a _DropFirstSequence, we need to fold in // the current drop count and drop limit so no data is lost. // // i.e. [1,2,3,4].dropFirst(1).dropFirst(1) should be equivalent to // [1,2,3,4].dropFirst(2). returnDropFirstSequence(_base, dropping: _limit + k) } }
/// A sequence that only consumes up to `n` elements from an underlying /// `Base` iterator. /// /// The underlying iterator's sequence may be infinite. @frozen publicstructPrefixSequence<Base: Sequence> { @usableFromInline internalvar _base: Base @usableFromInline internallet _maxLength: Int
@inlinable publicinit(_ base: Base, maxLength: Int) { _precondition(maxLength >= 0, "Can't take a prefix of negative length") _base = base _maxLength = maxLength } }
/// A sequence that lazily consumes and drops `n` elements from an underlying /// `Base` iterator before possibly returning the first available element. /// /// The underlying iterator's sequence may be infinite. @frozen publicstructDropWhileSequence<Base: Sequence> { publictypealiasElement = Base.Element @usableFromInline internalvar _iterator: Base.Iterator @usableFromInline internalvar _nextElement: Element? @inlinable internalinit(iterator: Base.Iterator, predicate: (Element) throws -> Bool) rethrows { _iterator = iterator _nextElement = _iterator.next() whilelet x = _nextElement, try predicate(x) { _nextElement = _iterator.next() } } @inlinable internalinit(_ base: Base, predicate: (Element) throws -> Bool) rethrows { self = tryDropWhileSequence(iterator: base.makeIterator(), predicate: predicate) } }
/// Returns a subsequence, up to the given maximum length, containing the /// final elements of the sequence. /// /// The sequence must be finite. If the maximum length exceeds the number of /// elements in the sequence, the result contains all the elements in the /// sequence. /// /// let numbers = [1, 2, 3, 4, 5] /// print(numbers.suffix(2)) /// // Prints "[4, 5]" /// print(numbers.suffix(10)) /// // Prints "[1, 2, 3, 4, 5]" /// /// - Parameter maxLength: The maximum number of elements to return. The /// value of `maxLength` must be greater than or equal to zero. /// /// - Complexity: O(*n*), where *n* is the length of the sequence. @inlinable public __consuming funcsuffix(_ maxLength: Int) -> [Element] { _Precondition(maxLength >= 0, "Can't take a suffix of negative length from a sequence") guard maxLength != 0else { return [] }
// FIXME: <rdar://problem/21885650> Create reusable RingBuffer<T> // Put incoming elements into a ring buffer to save space. Once all // elements are consumed, reorder the ring buffer into a copy and return it. // This saves memory for sequences particularly longer than `maxLength`. // 这里提到[RingBuffer](https://en.wikipedia.org/wiki/Circular_buffer)这个数据结构用于节省空间,这块还是值得注意的。因为如果使用正常的Array或者ContiguousArray,会创建一个和self本身同等大小的array,而使用RingBuffer则只会使用maxLength大小的空间. // 已经有相关RingBuffer(CircularBuffer)实现的[PR](https://github.com/apple/swift/pull/30242/files),最终没有merge到main var ringBuffer = ContiguousArray<Element>() ringBuffer.reserveCapacity(Swift.min(maxLength, underestimatedCount))
var i = 0
for element inself { if ringBuffer.count < maxLength { ringBuffer.append(element) } else { // RingBuffer相关操作,只保留buffer大小的数据,其他数据进行覆盖 ringBuffer[i] = element i = (i + 1) % maxLength } }
if i != ringBuffer.startIndex { // Rotate RingBuffer var rotated = ContiguousArray<Element>() rotated.reserveCapacity(ringBuffer.count) rotated += ringBuffer[i..<ringBuffer.endIndex] rotated += ringBuffer[0..<i] returnArray(rotated) } else { returnArray(ringBuffer) } }
/// Returns a sequence containing all but the given number of final /// elements. /// /// The sequence must be finite. If the number of elements to drop exceeds /// the number of elements in the sequence, the result is an empty /// sequence. /// /// let numbers = [1, 2, 3, 4, 5] /// print(numbers.dropLast(2)) /// // Prints "[1, 2, 3]" /// print(numbers.dropLast(10)) /// // Prints "[]" /// /// - Parameter n: The number of elements to drop off the end of the /// sequence. `n` must be greater than or equal to zero. /// - Returns: A sequence leaving off the specified number of elements. /// /// - Complexity: O(*n*), where *n* is the length of the sequence. @inlinable public __consuming funcdropLast(_ k: Int = 1) -> [Element] { _precondition(k >= 0, "Can't drop a negative number of elements from a sequence") guard k != 0else { returnArray(self) }
// FIXME: <rdar://problem/21885650> Create reusable RingBuffer<T> // Put incoming elements from this sequence in a holding tank, a ring buffer // of size <= k. If more elements keep coming in, pull them out of the // holding tank into the result, an `Array`. This saves // `k` * sizeof(Element) of memory, because slices keep the entire // memory of an `Array` alive. var result = ContiguousArray<Element>() // ringBuffer的大小同k相同,最后会保存被drop的元素 var ringBuffer = ContiguousArray<Element>() var i = ringBuffer.startIndex
for element inself { // 当ringbuffer小于k时,将元素放入ringbuffer中(holding tank) if ringBuffer.count < k { ringBuffer.append(element) } else { // pull them out of the holding tank into the result result.append(ringBuffer[i]) // 更新ringbuffer与index ringBuffer[i] = element i = (i + 1) % k } } returnArray(result) }
extensionSequencewhereElement: Equatable{ /// 直接比较两个两个类型的Sequence元素是否相同,可以省去转换成相同type的步骤 /// Returns a Boolean value indicating whether this sequence and another /// sequence contain the same elements in the same order. /// /// At least one of the sequences must be finite. /// /// This example tests whether one countable range shares the same elements /// as another countable range and an array. /// /// let a = 1...3 /// let b = 1...10 /// /// print(a.elementsEqual(b)) /// // Prints "false" /// print(a.elementsEqual([1, 2, 3])) /// // Prints "true" /// /// - Parameter other: A sequence to compare to this sequence. /// - Returns: `true` if this sequence and `other` contain the same elements /// in the same order. /// /// - Complexity: O(*m*), where *m* is the lesser of the length of the /// sequence and the length of `other`. @inlinable publicfuncelementsEqual<OtherSequence: Sequence>( _ other: OtherSequence ) -> BoolwhereOtherSequence.Element == Element { returnself.elementsEqual(other, by: ==) } }
extensionSequence{ /// Returns an array containing the concatenated results of calling the /// given transformation with each element of this sequence. /// /// Use this method to receive a single-level collection when your /// transformation produces a sequence or collection for each element. /// /// In this example, note the difference in the result of using `map` and /// `flatMap` with a transformation that returns an array. /// /// let numbers = [1, 2, 3, 4] /// /// let mapped = numbers.map { Array(repeating: $0, count: $0) } /// // [[1], [2, 2], [3, 3, 3], [4, 4, 4, 4]] /// /// let flatMapped = numbers.flatMap { Array(repeating: $0, count: $0) } /// // [1, 2, 2, 3, 3, 3, 4, 4, 4, 4] /// /// In fact, `s.flatMap(transform)` is equivalent to /// `Array(s.map(transform).joined())`. /// /// - Parameter transform: A closure that accepts an element of this /// sequence as its argument and returns a sequence or collection. /// - Returns: The resulting flattened array. /// /// - Complexity: O(*m* + *n*), where *n* is the length of this sequence /// and *m* is the length of the result. @inlinable publicfuncflatMap<SegmentOfResult: Sequence>( _ transform: (Element)throws -> SegmentOfResult ) rethrows -> [SegmentOfResult.Element] { var result: [SegmentOfResult.Element] = [] for element inself { /// 有别于map的地方 result.append(contentsOf: try transform(element)) } return result } }
extensionSequence{ /// Returns an array containing the non-`nil` results of calling the given /// transformation with each element of this sequence. /// /// Use this method to receive an array of non-optional values when your /// transformation produces an optional value. /// /// In this example, note the difference in the result of using `map` and /// `compactMap` with a transformation that returns an optional `Int` value. /// /// let possibleNumbers = ["1", "2", "three", "///4///", "5"] /// /// let mapped: [Int?] = possibleNumbers.map { str in Int(str) } /// // [1, 2, nil, nil, 5] /// /// let compactMapped: [Int] = possibleNumbers.compactMap { str in Int(str) } /// // [1, 2, 5] /// /// - Parameter transform: A closure that accepts an element of this /// sequence as its argument and returns an optional value. /// - Returns: An array of the non-`nil` results of calling `transform` /// with each element of the sequence. /// /// - Complexity: O(*m* + *n*), where *n* is the length of this sequence /// and *m* is the length of the result. @inlinable // protocol-only publicfunccompactMap<ElementOfResult>( _ transform: (Element)throws -> ElementOfResult? ) rethrows -> [ElementOfResult] { returntry _compactMap(transform) }
// The implementation of compactMap accepting a closure with an optional result. // Factored out into a separate function in order to be used in multiple // overloads. @inlinable // protocol-only @inline(__always) publicfunc_compactMap<ElementOfResult>( _ transform: (Element)throws -> ElementOfResult? ) rethrows -> [ElementOfResult] { var result: [ElementOfResult] = [] for element inself { /// 与map的区别 iflet newElement = try transform(element) { result.append(newElement) } } return result } }
Two Core Abilities for Thriving in the New Economy
The ability to quickly master hard things.
The ability to produce at an elite level, in terms of both quality and speed.
Deep Work Helps You Quickly Learn Hard Things
1
Let your mind become a lens, thanks to the converging rays of attention;
let your soul be all intent on whatever it is that is established in your mind as a dominant, wholly absorbing idea.
-- Antonin-Dalmace Sertillanges
Deliberate practice
your attention is focused tightly on a specific skill you’re trying to improve or an idea you’re trying to master;
you receive feedback so you can correct your approach to keep your attention exactly where it’s most productive.
Deep Work Helps You Produce at an Elite Level
High-Quality Work Produced = (Time Spent) x (Intensity of Focus)
Chapter Two - Deep work is rare:
1
To do real good physics work, you do need absolute solid lengths
of time...it needs a lot of concentration...if you have a job
administrating anything, you don't have the time. So, I have
invented another myth for myself: that I'm irresponsible.
I'm actively irresponsible. I tell everyone I don't do anything.
If anyone asks me to be on a committee for admissions, "no," I tell
them:I'm irresponsible. -- Feynman
Busyness as Proxy for Productivity
In the absence of clear indicators of what it means to be productive and valuable in their jobs, many knowledge workers turn back toward an industrial indicator of productivity: doing lots of stuff in a visible manner.
Deep work is at a servere disadvantage in a technopoly because it builds on values like quality, craftsmanship, and mastery that are decidedly old-fashioned and nontechnological. Even worse, to support deep work often requires the rejection of much of what is new and high-tech. Deep work is exiled in favor of more distracting high-tech behaviors.
Chapter Three - Deep Work Is Meaningful
A Neurological Argument for Depth
Your world is the outcome of what you pay attention to, so consider for a moment the type of mental world constructed when you dedicate significant time to deep endeavors. There’s gravity and snese of imprortance inherent in deep work.
The idle mind is the devil’s workshop. When you lose focus, your mind tends to fix on what could be wrong with your life instead of what’s right.
A workday driven by the shallow, from a neurological perspective, is likely to be a draining and upsetting day, even if most of the shallow things that capture your attention seem harmless or fun.
A Pssychological Argument for Depth
Ironically, jobs are actually easier to enjoy than free time, because like flow activities they have built-in goals, feedback rules, and challenges, all of which encourage one to become involved in one’s work, to concentrate and lose oneself in it. Free time, on the other hand, is unstructured, and requires much greater effort to be shaped into something that can be enjoyed.
A Philosophical Argument for Depth
Beautiful code is short and concise, so if you were to give that code to another programmer they would say, “oh, that’s well written code.” It’s much like as if you were writing a poem.
Within the overall structure of a project there is always room for individuality and craftsmanship…One hundred years from now, our engineering may seem as archaic as the techniques used by medieval cathedral builders seem to today’s civil engineers, while our craftsmanship will still be honored.
Chapter Four - Rule 1: Work Deeply
You have a finite amount of willpower that becomes depleted as you use it.
The key to developing a deep work habit is to move beyond good intentions and add routines and rituals to your working life designed to minimize the amount of your limited willpower necessary to transition into and maintain a state of unbroken concentration.
warning: You must be careful to choose a philosophy that fits your specific circumstances.
The monastic Philosophy of Deep Work Scheduling
This philosophy attempts to maximize deep efforts by eliminating or radically minimizing shallow obligations.
The Bimodal Philosophy of Deep Work Scheduling
This philosophy asks that you divide your time, dedicating some clearly defined staretches to deep pursuits and leaving the rest open to everything else.
The Rhythmic Philosophy of Deep Work Scheduling
This philosophy argues that the easiest way to consistently start deep work sessions is to transform them into a simple regular habit. The goal, in other words, is to generate a rhythm for this work that removes the need for you to invest energy in deciding if and when you’re going to go deep. The chain method is a good example of the rhythmic philosophy of deep work scheduling because it combines a simple scheduling euristic, with an easy way to remind yourself to do the work: the big red Xs on the calendar.
The Jourualistic Philosophy of Deep Work Scheduling
I call this approach, in which you fit deep work wherever you can into your schedule, the journalist philosophy. This approach is not for the deep work novice. As I established in the opening to this rule, the ability to rapidly switch your mind from shallow to deep mode doesn’t come naturally. Without practice, such switches can seriously deplete your finite willpower reserves. This habit also requires a sense of confidence in your abilities.
Deep work ritual
Where you’ll work and for how long. Your ritual needs to specify a location for your deep work efforts.
How you’ll work once you start to work. Your ritual needs rules and processes to keep your efforts structured.
How you’ll support you work. Your ritual needs to ensure your brain gets the support it needs to keep operating at a high level of depth.
Make Grand Gestures
The concept is simple: By leveraging a radical change to your normal environment, coupled perhaps with a significant investment of effort or money, all dedicated toward supporting a deep work task, you increase the perceived importance of the task. This boost in importance reduces your mind’s instinct to procrastinate and delivers an injection of motivation and energy.
The 4 disciplines of excution
Discipline 1: Focus on the wildly important
“The more you try to do, the less you actually accomplish.” execution should be aimed at a small number of “wildly important goals.” This simplicity will help focus an organization’s energy to a sufficient intensity to ignite real results.
For an individual focused on deep work, the implication is that you should identify a small number of ambitious outcomes to pursue with your deep work hours.
Discipline 2: Act on the lead measures
once you’ve identified a wildly important goal, you need to measure your success.
For an individual focused on deep work, it’s easy to identify the relevant lead measure: time spent in a state of deep work dedicated toward your wildly important goal.
Discipline 3: Keep a compilling scoreboard.
Discipline 4: Create a cadence of accountability.
Why a shutdown will be proftable to your ability to produce valuable output.
Reason 1: Downtime aids insights.
Reason 2: Downtime helps recharge the energy needed to work deeply.
Reason 3: The work that evening downtime replaces is usually not that important.
Rule 2: Embrace boredom
Rule 1: taught you how to integrate deep work into your schedule and support it with routines and rituals designed to help you consistently reach the current limiit of your concentration ability.
Rule 2: will help you significantly improve this limit. The starategies that follow are motivated by the key idea that getting the most out of your deep work habit requires training, and as clarified previously, this training must address two goals:
improving your ability to concentrate intensely and
overcoming your desire for distraction
Don’t take breaks from distraction, instead take breaks from focus. point 1: this strategy works even if your job requires lots of internet use and/or prompt e-mail replies. point 2: regardless of how you schedule your internet blocks, you must keep the time outside those blocks absolutely free from internet use. point 3: scheduling internet use at home as well as at work can further improve your concentration traning.