Four Thousand Weeks

Introduction: In the long run, we’re all dead

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.

麦肯锡方法

“二八法则” 与其他

二八法则

“二八法则” 时管理咨询业甚至商业领域里最大的真理之一。它无处不在:销售额的80%来自20%的销售队伍,一个秘书20%的工作会占据他80%的时间,20%的人掌握着80%的财富。”二八法则”也不是屡试不爽的,但假如你注意搜寻公司里”二八法则”的例子,就会相处改进它的方法。

不要妄想烧干大海

要更聪明的工作,而不是更辛苦的工作。很多数据都与你的研究问题相关,很多分析可以展开,但大多数你都得忽略掉。

把海水烧干就是试图去分析得面面俱到。要有选择,厘清手头需要优先解决的事情。当已经做得足够多的时候,就停下来。否则,你花费许多时间和精力,结果却得不偿失,就像你烧干了大海,却只能得到一点盐。

找到关键驱动因素

影响企业因素有很多,要关注最重要的那些 – 关键驱动因素。

电梯法则

你已经对自己的解决方案了如指掌,可以在30秒内向客户进行准确无误的解释。假如能做到这一点,就证明你对自己的工作充分了解,并足以推销你的解决方案了。

先摘好摘的果实

有时候,在解决问题的过程中,机遇的出现使你轻松获胜,或者在整个问题得到解决之前获得显著成效。抓住这些机遇!机遇并不会为你和团队创造全部胜利,但鼓舞了士气,增加了信任,让那些关注你的人知道你很能干而且很认真。

每天绘制一张图表

在解决问题的过程中,每天都会有新收获。把它们记录下来,将有助于推进你的思考。无论你是否采用这个方法,请记住:一旦你将想法记录在纸上,就永远也不会忘记。

一次只做一件事

你不可能做所有的事,所以也不要尝试这样,将自己分内的事做好就可以了。就好像打棒球一样,要一垒一垒地打。

  • 你不可能事必躬亲
  • 如果有一次,你设法去做了每一件事,就会让周围的人对你产生不切实际的期望
  • 假如没能满足这些期望,将很难重新获得信任

以大局为重

时不时停下思路,问自己几个基本的问题:你现在所做的工作事如何帮助解决问题的?它事如何推进思考的?眼下做的事情是不是最重要的?如果所做的工作对解决问题没有帮助,为何还要继续?

如实相告,坦诚相待

公司在每名新员工入职之初就向他们灌输职业操守的概念,这很正确。职业操守的一个重要方面就是诚信—对客户,团队成员以及你自己讲诚信。诚信包括在你一筹莫展的时候勇于承认。勇于承认的代价远远小于虚张声势的代价。

不接受“我没有想法”这种回答

只要稍加探究,就会发现人们总是有想法的。问他们一些有针对性的问题,就会为他们知道的东西之多而感到吃惊。结合他们的知识和一些有根据的推测,基本上就与问题解决方案距离不远了。

悉达多

以下摘抄自《悉达多》

他首先学会了倾听,学会了用一颗平静的心、一个敞开的灵魂去关注一切,没有激情,没有期盼,没有论断,没有成见。

时间并不存在。

一切痛苦、折磨和恐惧不都来自时间吗?人一旦战胜了时间,就如将时间从人的思想中抹掉,那么世界上的一切困难和敌对不就都克服了吗?

他已不像从前那样聪明和傲慢,而是更热情、好奇、投入。再见到那些普通旅客、孩子般的人、商人、战士、女人时,他也不似从前那般陌生:他理解他们,理解并分享他们仅凭冲动和愿望而非思想和理智的生活,他觉得自己跟他们一样。尽管他已接近圆满,正承受着最后的伤口,他仍视那些孩子般的世人为兄弟,他不再嘲笑他们的虚荣心、占有欲和荒谬行为,而是开始理解、热爱甚至尊重他们。母亲对孩子盲目的爱,狂妄自大的父亲愚蠢盲目地为独子骄傲,年轻虚荣的女子盲目疯狂地追求珠宝和男人欣赏的目光,所有这些幼稚的冲动,这些简单、愚蠢但又极其强烈鲜活的冲动和欲望,对现在的悉达多来说,已不再是幼稚。他看到人们为自己而活,看到他们不断取得成就、旅行、征战、受苦,他可以因此而爱他们;

觉悟,对生命同一的觉悟。

每个人都在朝着自己的目标前进,又都被目标困扰,为目标受苦。

人在探索时,他的双眼往往只看得到探索的东西,而最终只会毫无收获。因为他只想着探索的东西,他有目标,且只关心目标。探索意味着拥有目标,而发现意味着自由、开放、没有目标。尊敬的僧人,或许你的确是一位探索者,因为你在为目标奋斗,你眼前的很多东西,你都没看到。

我看到的一切都是好的,死即生,罪恶即神圣,智慧即愚蠢,一切都是如此。我只需遵循从和热爱这一切;这同时对我也有好处,都无法伤害我。我的躯体和灵魂都经历过罪恶、性欲、追求过财富、虚荣、感受过最可耻的绝望,只为学会放弃反抗,学会爱这个世界,不再将其与我幻想的完美世界相比,而是让世界保持原来的样子,然后爱它、融入它。

我唯一感兴趣的是热爱世界、不轻视世界、不憎恶世界和我自己,能够充满爱意、钦佩和敬意看待世界、我和万物。

信心

如果你认为自己会失败,那么你已经失败了。
如果你认为自己不敢做,那么你肯定踌躇不前。
如果你想获胜,却认为无力制胜,
那么几乎可以断定,你与胜利无缘。
如果你认为自己会输,那么你已经输了。
放眼世界,我们发现,
有志者事竟成—
一切都与心态有关。
如果你认为自己出类拔萃,那么你就是如此,
你心高志远,
你相信自己,
胜利总会垂青于你。
人生的赛场并非总呼唤更快、更强,
最后的胜利,
属于那个相信自己能行的你!

Combine: Publisher

Publisher

The publisher is the provider of data.

Empty

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/// 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, *)
public struct Empty<Output, Failure> : Publisher, Equatable where Failure : Error {

/// Creates an empty publisher.
///
/// - Parameter completeImmediately: A Boolean value that indicates whether the publisher should immediately finish.
public init(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.
public init(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.
public let 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.
public func receive<S>(subscriber: S) where Output == 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`.
public static func == (lhs: Empty<Output, Failure>, rhs: Empty<Output, Failure>) -> Bool
}

Just

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/// 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, *)
public struct Just<Output> : Publisher {

/// The kind of errors this publisher might publish.
///
/// Use `Never` if this `Publisher` does not publish errors.
public typealias Failure = Never

/// The one element that the publisher emits.
public let output: Output

/// Initializes a publisher that emits the specified output just once.
///
/// - Parameter output: The one element that the publisher emits.
public init(_ 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.
public func receive<S>(subscriber: S) where Output == S.Input, S : Subscriber, S.Failure == Just<Output>.Failure
}

Future

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/// 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, *)
final public class Future<Output, Failure> : Publisher where Failure : 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.
public typealias Promise = (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.
public init(_ 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.
final public func receive<S>(subscriber: S) where Output == S.Input, Failure == S.Failure, S : Subscriber
}

Deferrred

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/// 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, *)
public struct Deferred<DeferredPublisher> : Publisher where DeferredPublisher : Publisher {

/// The kind of values published by this publisher.
public typealias Output = DeferredPublisher.Output

/// The kind of errors this publisher might publish.
public typealias Failure = DeferredPublisher.Failure

/// The closure to execute when this deferred publisher receives a subscription.
///
/// The publisher returned by this closure immediately receives the incoming subscription.
public let createPublisher: () -> DeferredPublisher

/// Creates a deferred publisher.
///
/// - Parameter createPublisher: The closure to execute when calling `subscribe(_:)`.
public init(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.
public func receive<S>(subscriber: S) where S : Subscriber, DeferredPublisher.Failure == S.Failure, DeferredPublisher.Output == S.Input
}

Fail

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/// A publisher that immediately terminates with the specified error.
@available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
public struct Fail<Output, Failure> : Publisher where Failure : Error {

/// Creates a publisher that immediately terminates with the specified failure.
///
/// - Parameter error: The failure to send when terminating the publisher.
public init(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.
public init(outputType: Output.Type, failure: Failure)

/// The failure to send when terminating the publisher.
public let 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.
public func receive<S>(subscriber: S) where Output == S.Input, Failure == S.Failure, S : Subscriber
}

Sequence

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
extension Publishers {

/// 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.
public struct Sequence<Elements, Failure> : Publisher where Elements : Sequence, Failure : Error {

/// The kind of values published by this publisher.
public typealias Output = Elements.Element

/// The sequence of elements to publish.
public let sequence: Elements

/// Creates a publisher for a sequence of elements.
///
/// - Parameter sequence: The sequence of elements to publish.
public init(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.
public func receive<S>(subscriber: S) where Failure == S.Failure, S : Subscriber, Elements.Element == S.Input
}
}

Record

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/// 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, *)
public struct Record<Output, Failure> : Publisher where Failure : Error {

/// The recorded output and completion.
public let 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.
public init(record: (inout Record<Output, Failure>.Recording) -> Void)

/// Creates a record publisher from an existing recording.
///
/// - Parameter recording: A previously-recorded recording of published elements and a completion.
public init(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.
public init(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.
public func receive<S>(subscriber: S) where Output == S.Input, Failure == S.Failure, S : Subscriber

/// A recorded sequence of outputs, followed by a completion value.
public struct Recording {

public typealias Input = Output

/// The output which will be sent to a `Subscriber`.
public var output: [Output] { get }

/// The completion which will be sent to a `Subscriber`.
public var completion: Subscribers.Completion<Failure> { get }

/// Set up a recording in a state ready to receive output.
public init()

/// Set up a complete recording with the specified output and completion.
public init(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.
public mutating func receive(_ input: Record<Output, Failure>.Recording.Input)

/// Add a completion to the recording.
///
/// A `fatalError` will be raised if more than one completion is added.
public mutating func receive(completion: Subscribers.Completion<Failure>)
}
}

Share

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/// 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.
final public class Share<Upstream> : Publisher, Equatable where Upstream : Publisher {

/// The kind of values published by this publisher.
///
/// This publisher uses its upstream publisher's output type.
public typealias Output = Upstream.Output

/// The kind of errors this publisher might publish.
///
/// This publisher uses its upstream publisher's failure type.
public typealias Failure = Upstream.Failure

/// The publisher from which this publisher receives elements.
final public let 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.
public init(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.
final public func receive<S>(subscriber: S) where S : 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`.
public static func == (lhs: Publishers.Share<Upstream>, rhs: Publishers.Share<Upstream>) -> Bool
}

Multicast

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/// 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.
final public class Multicast<Upstream, SubjectType> : ConnectablePublisher where Upstream : 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.
public typealias Output = Upstream.Output

/// The kind of errors this publisher might publish.
///
/// This publisher uses its upstream publisher's failure type.
public typealias Failure = Upstream.Failure

/// The publisher from which this publisher receives its elements.
final public let upstream: Upstream

/// A closure that returns a subject each time a subscriber attaches to the multicast publisher.
final public let 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.
public init(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.
final public func receive<S>(subscriber: S) where S : 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.
final public func connect() -> Cancellable
}

ConnectablePublisher

connect

某些情况下,我们希望在Publisher产生数据前对其进行相关配置,而不是当有Subscriber时,就直接开始产生数据。

Apple文档上提供了一个例子,就是当连个Subscriber要share一个DataTaskPublisher, 在正常的Publisher情况下,当第一个Subscriber进行订阅时,Task就会启动,这样有可能在第二个Subscriber订阅时,已经错过了receiveValue事件。所以我们需要ConnectablePublisher能在等待一个connect事件后,才开始产生数据,而不是有订阅就开始产生数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
let url = URL(string: "https://example.com/")!
let connectable = URLSession.shared
.dataTaskPublisher(for: url)
.map() { $0.data }
.catch() { _ in Just(Data() )}
.share()
.makeConnectable()

cancellable1 = connectable
.sink(receiveCompletion: { print("Received completion 1: \($0).") },
receiveValue: { print("Received data 1: \($0.count) bytes.") })

DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.cancellable2 = connectable
.sink(receiveCompletion: { print("Received completion 2: \($0).") },
receiveValue: { print("Received data 2: \($0.count) bytes.") })
}

DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.connection = connectable.connect()
}

autoconnect

在某些场景下,像Timer.TimerPublisher, 每次使用前需要显示调用connect会显得很麻烦,当你根本不需要其他多余配置,或者有多个订阅者。在这种情况下,我们可以使用autoconnect。.

1
2
3
4
5
let cancellable = Timer.publish(every: 1, on: .main, in: .default)
.autoconnect()
.sink() { date in
print ("Date now: \(date)")
}

Combine: Introduction

Combine

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 release of the Combine framework - in iOS 13 prior to iOS 13.3 and macOS prior to 10.15.2 - when the subscriber requested data with 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 where data might appear to be lost.

Due to this, in iOS 13.3 and later Combine releases, the process of requesting demand has been updated to a synchronous/blocking call.

In practice, this means that you can be a bit more certain of having any pipelines created and fully engaged prior to a publisher receiving the request to send any data.

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

  1. When the subscriber is attached to a publisher, it starts with a call to .subscribe(_: Subscriber).

  2. The publisher in turn acknowledges the subscription calling receive(subscription: Subscription).

  3. After the subscription has been acknowledged, the subscriber requests N values with request(_: Demaind).

  4. 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.

  5. Any time after the subscription has been acknowledged, the subscriber may send a cancellation with .cancel().

  6. 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.

  • Defines how values and errors are produced
  • Value type
  • Allows registration of a Subscriber
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
public protocol Publisher {

/// 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.
func receive<S>(subscriber: S) where S : 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.

  • Receives values and a completion

  • Reference type

1
2
3
4
5
6
7
8
9
10
11
protocol Subscriber {
associatedtype Input
associatedtype Failure: Error

// once
func receive(subscription: Subscription)
// zero or More values
func receive(_ input: Input) -> Subscribers.Demaind
// At most one completion
func receive(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
      }
    • Subjects

      • Behave like both Publisher and Subscriber
      • Broadcast values to multiple subscribers

        1
        2
        3
        4
        protocol Subject: Publisher, AnyObject {
        func send(_ value: Output)
        func send(completion: Subscribers.Completion<Failure>)
        }
      • Kinds of Subjects

        • Passthrough
        • CurrentValue
    • SwiftUI

Operators

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.

  • Adopts Publisher
  • Describes a behavior for changing values
  • Subscribes to a Publisher (“upstream”)
  • Sends result to a Subscriber (“downstream”)
  • Value type
  • Declarative Operator API
    • Functional transformations
    • List operations
    • Error handling
    • Thread or queue movement
    • Scheduling and time

Subject

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/// 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, *)
public protocol Subject : AnyObject, Publisher {

/// Sends a value to the subscriber.
///
/// - Parameter value: The value to send.
func send(_ 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.
func send(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.
func send(subscription: Subscription)
}

Kinds of Subject

  • PassthroughSubject
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/// 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, *)
final public class PassthroughSubject<Output, Failure> : Subject where Failure : Error {

public init()

/// 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.
final public func send(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.
final public func receive<S>(subscriber: S) where Output == S.Input, Failure == S.Failure, S : Subscriber

/// Sends a value to the subscriber.
///
/// - Parameter value: The value to send.
final public func send(_ 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.
final public func send(completion: Subscribers.Completion<Failure>)
}
  • CurrentValueSubject
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/// 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, *)
final public class CurrentValueSubject<Output, Failure> : Subject where Failure : Error {

/// The value wrapped by this subject, published as a new element whenever it changes.
final public var value: Output

/// Creates a current value subject with the given initial value.
///
/// - Parameter value: The initial value to publish.
public init(_ 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.
final public func send(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.
final public func receive<S>(subscriber: S) where Output == S.Input, Failure == S.Failure, S : Subscriber

/// Sends a value to the subscriber.
///
/// - Parameter value: The value to send.
final public func send(_ 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.
final public func send(completion: Subscribers.Completion<Failure>)
}

Scheduler

When

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/// 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, *)
public protocol Scheduler {

/// Describes an instant in time for this scheduler.
associatedtype SchedulerTimeType : Strideable where Self.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.
func schedule(options: Self.SchedulerOptions?, _ action: @escaping () -> Void)

/// Performs the action at some time after the specified date.
func schedule(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.
func schedule(after date: Self.SchedulerTimeType, interval: Self.SchedulerTimeType.Stride, tolerance: Self.SchedulerTimeType.Stride, options: Self.SchedulerOptions?, _ action: @escaping () -> Void) -> Cancellable
}

Where

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
@available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
extension Publisher {

/// 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.
public func receive<S>(on scheduler: S, options: S.SchedulerOptions? = nil) -> Publishers.ReceiveOn<Self, S> where S : Scheduler
}

Swift Source Code: ContiguousArray

ContiguousArray

A contiguously stored array.

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.

ContiguousArray 是对 _buffer: _ContiguousArrayBuffer<Element> 的一个封装.

_buffer 是一个对 _storage: __ContiguousArrayStorageBase的封装.

Types

ContiguousArray

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@frozen
public struct ContiguousArray<Element>: _DestructorSafeContainer {
@usableFromInline
internal typealias _Buffer = _ContiguousArrayBuffer<Element>

@usableFromInline
internal var _buffer: _Buffer

/// Initialization from an existing buffer does not have "array.init"
/// semantics because the caller may retain an alias to buffer.
@inlinable
internal init(_buffer: _Buffer) {
self._buffer = _buffer
}
}

_ContiguousArrayBuffer: _ArrayBufferProtocol

1
2
3
4
5
6
@usableFromInline
@frozen
internal struct _ContiguousArrayBuffer<Element>: _ArrayBufferProtocol {
@usableFromInline
internal var _storage: __ContiguousArrayStorageBase
}

// __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.
//

ContiguousArrayStorageBase: SwiftNativeNSArrayWithContiguousStorage

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/// 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
internal class __ContiguousArrayStorageBase: __SwiftNativeNSArrayWithContiguousStorage {
@Usablefrominline
final var countAndCapacity: _ArrayBody

@inlinable
@nonobjc
internal init(_doNotCallMeBase: ()) {
_internalInvariantFailure("creating instance of __ContiguousArrayStorageBase")
}

#if _runtime(_ObjC)
internal override func withUnsafeBufferOfObjects<R>(
_ body: (UnsafeBufferPointer<AnyObject>)
throws -> R

) rethrows -> R {
if let 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`.
internal func _withVerbatimBridgedUnsafeBuffer<R>(
_ body: (UnsafeBufferPointer<AnyObject>)
throws -> R

) rethrows -> R? {
_internalInvariantFailure(
"Concrete subclasses must implement _withVerbatimBridgedUnsafeBuffer")
}

internal func _getNonVerbatimBridgingBuffer() -> _BridgingBuffer {
_internalInvariantFailure(
"Concrete subclasses must implement _getNonVerbatimBridgingBuffer")
}

@objc(mutableCopyWithZone:)
dynamic internal func mutableCopy(with _: _SwiftNSZone?) -> AnyObject {
let arr = Array<AnyObject>(_ContiguousArrayBuffer(self))
return _SwiftNSMutableArray(arr)
}

@objc(indexOfObjectIdenticalTo:)
dynamic internal func index(ofObjectIdenticalTo object: AnyObject) -> Int {
let arr = Array<AnyObject>(_ContiguousArrayBuffer(self))
return arr.firstIndex { $0 === object } ?? NSNotFound
}
#endif

@inlinable
internal func canStoreElements(ofDynamicType _: Any.Type) -> Bool {
_internalInvariantFailure(
"Concrete subclasses must implement canStoreElements(ofDynamicType:)")
}

/// A type that every element in the array is.
@inlinable
internal var staticElementType: Any.Type {
_internalInvariantFailure(
"Concrete subclasses must implement staticElementType")
}

@inlinable
deinit {
_internalInvariant(
self !== _emptyArrayStorage, "Deallocating empty array storage?!")
}
}

}

// 直接对内存进行操作
@usableFromInline
@frozen
internal struct _ContiguousArrayBuffer<Element>: _ArrayBufferProtocol {
@usableFromInline
internal var _storage: __ContiguousArrayStorageBase

/// 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
internal init(
_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)

let storageAddr = UnsafeMutableRawPointer(Builtin.bridgeToRawPointer(_storage))
if let allocSize = _mallocSize(ofAllocation: storageAddr) {
let endAddr = storageAddr + allocSize
let realCapacity = endAddr.assumingMemoryBound(to: Element.self) - firstElementAddress
_initStorageHeader(
count: uninitializedCount, capacity: realCapacity)
} else {
_initStorageHeader(
count: uninitializedCount, capacity: realMinimumCapacity)
}
}
}

/// Initialize the body part of our storage.
///
/// - Warning: does not initialize elements
@inlinable
internal func _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)
}

@frozen
@usableFromInline
internal struct _ArrayBody {
@usableFromInline
internal var _storage: _SwiftArrayBodyStorage

@inlinable
internal init(
count: Int, capacity: Int, elementTypeIsBridgedVerbatim: Bool = false
) {
_internalInvariant(count >= 0)
_internalInvariant(capacity >= 0)

_storage = _SwiftArrayBodyStorage(
count: count,
_capacityAndFlags:
(UInt(truncatingIfNeeded: capacity) &<< 1) |
(elementTypeIsBridgedVerbatim ? 1 : 0))
}


struct _SwiftArrayBodyStorage {
__swift_intptr_t count;
__swift_uintptr_t _capacityAndFlags;
};

// Swift Array 转换NSArray O(1)

SwiftNativeNSArrayWithContiguousStorage : SwiftNativeNSArray (NSArray)

__SwiftNativeNSArrayWithContiguousStorage (non-objc)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/// 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
internal class __SwiftNativeNSArrayWithContiguousStorage
: __SwiftNativeNSArray { // Provides NSArray inheritance and native refcounting


@inlinable
@nonobjc internal override init() { super.init() }

@inlinable
deinit {}

// Operate on our contiguous storage
internal func withUnsafeBufferOfObjects<R>(
_ body: (UnsafeBufferPointer<AnyObject>)
throws -> R

) rethrows -> R {
_internalInvariantFailure(
"Must override withUnsafeBufferOfObjects in derived classes")
}
}

@_fixed_layout
@usableFromInline
internal class __SwiftNativeNSArray {
@inlinable
internal init() {}
@inlinable
deinit {}
}

// Empty shim version for non-objc platforms.
@usableFromInline
@_fixed_layout
internal class __SwiftNativeNSArrayWithContiguousStorage {
@inlinable
internal init() {}

@inlinable
deinit {}
}

__SwiftNativeNSArray

provides NSArray inheritance and native refcounting

1
2
3
4
5
6
7
8
@_fixed_layout
@usableFromInline
internal class __SwiftNativeNSArray {
@inlinable
internal init() {}
@inlinable
deinit {}
}

Functions

Copy on Write

append 为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/// 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")
public mutating func append(_ 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()
}

@inlinable
@_semantics("array.make_mutable")
internal mutating func _makeUniqueAndReserveCapacityIfNotUnique() {
if _slowPath(!_buffer.beginCOWMutation()) {
_createNewBuffer(bufferIsUnique: false,
minimumCapacity: count &+ 1,
growForAppend: true)
}
}

/// 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)
internal mutating func _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)
let c = 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)
}

Swift Source Code: Collection

Summary

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.

Types

IndexingIterator

  • IndexingIterator 是collection类型默认的iterator实现
  • 自定义Collection所需要的最小实现只需要startIndex, endIndex, subscript方法
  • IndexingIterator实现了IteratorProtocol, Sequence, Sendable等protocol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/// 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
public struct IndexingIterator<Elements: Collection> {
@usableFromInline
internal let _elements: Elements
@usableFromInline
internal var _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
}
}

extension IndexingIterator: IteratorProtocol, Sequence {
public typealias Element = Elements.Element
public typealias Iterator = IndexingIterator<Elements>
public typealias SubSequence = AnySequence<Element>

/// 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)
public mutating func next() -> Elements.Element? {
if _position == _elements.endIndex { return nil }
let element = _elements[_position]
_elements.formIndex(after: &_position)
return element
}
}

extension IndexingIterator: Sendable
where Elements: Sendable, Elements.Index: Sendable { }

Collection

A sequence whose elements can be traversed multiple times, nondestructively, and accessed by an indexed subscript.

  • Accessing Individual Elements
  • Accessing Slices of a Collection
  • Traversing a Collection
  • Conforming to the Collection Protocol
    • The startIndex and endIndex properties
    • A subscript
    • index(after:)
  • Expected Performance
    • startIndex and endIndex and subscript access O(1)
    • forward or bidirectional collection accessing its count property is an O(n)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
public protocol Collection: 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")
typealias IndexDistance = 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 func makeIterator() -> 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>
where SubSequence.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>
where Indices.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])
var indices: 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.
var count: 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`.
func index(_ 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`.
func index(
_ 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.
func distance(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>)

func _failEarlyRangeCheck(_ index: Index, bounds: ClosedRange<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`.
func index(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`.
func formIndex(after i: inout Index)
}

Functions

randomeElement

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
  /// 这两个方法我觉得可以用在测试代码中,如可以方便的随机选取登陆用户账号密码用于测试,或者随机一个dataset传入要测试的方法中
@inlinable
public func randomElement<T: RandomNumberGenerator>(
using generator: inout T
)
-> Element? {

guard !isEmpty else { return nil }
let random = Int.random(in: 0 ..< count, using: &generator)
let idx = index(startIndex, offsetBy: random)
return self[idx]
}
@inlinable
public func randomElement() -> 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
public struct SystemRandomNumberGenerator: RandomNumberGenerator, Sendable {
/// Creates a new instance of the system's default random number generator.
@inlinable
public init() { }

/// Returns a value from a uniform, independent distribution of binary data.
///
/// - Returns: An unsigned 64-bit random value.
@inlinable
public mutating func next() -> 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
public mutating func popFirst() -> Element? {
// TODO: swift-3-indexing-model - review the following
guard !isEmpty else { return nil }
/// 一定有倔种来告诉我,我们在swift不推荐使用“!”
let element = first!
/// 你删除first这么带劲吗?
self = self[index(after: startIndex)..<endIndex]
return element
}

isEmpty

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/// 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
public var isEmpty: Bool {
return startIndex == endIndex
}

Swift Source Code: Sequence

Summary

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).

Types

IteratorProtocol

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public protocol IteratorProtocol {
/// 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`.
mutating func next() -> Element?
}

Sequence

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
public protocol Sequence {
/// 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: IteratorProtocol where Iterator.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")
typealias Generator = 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 func makeIterator() -> 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`.
func withContiguousStorageIfAvailable<R>(
_ body: (_ buffer: UnsafeBufferPointer<Element>)
throws -> R

) rethrows -> R?
}

DropFirstSequence, PrefixSequence, DropWhileSequence

在dropFirst,prefix, drop(while:) 方法中,返回的并非为Array或者Sequence类型,而是返回了对应的XXSequence struct 类型。看注释上说时可以lazily consume. 这几类Sequence有些类似Box/Wrapper Sequence.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/// 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
public struct DropFirstSequence<Base: Sequence> {
@usableFromInline
internal let _base: Base
@usableFromInline
internal let _limit: Int

@inlinable
public init(_ base: Base, dropping limit: Int) {
_precondition(limit >= 0,
"Can't drop a negative number of elements from a sequence")
_base = base
_limit = limit
}
}

extension DropFirstSequence: Sequence {
public typealias Element = Base.Element
public typealias Iterator = Base.Iterator
public typealias SubSequence = AnySequence<Element>

@inlinable
public __consuming func makeIterator() -> Iterator {
var it = _base.makeIterator()
var dropped = 0
while dropped < _limit, it.next() != nil { dropped &+= 1 }
return it
}

@inlinable
public __consuming func dropFirst(_ 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).
return DropFirstSequence(_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
public struct PrefixSequence<Base: Sequence> {
@usableFromInline
internal var _base: Base
@usableFromInline
internal let _maxLength: Int

@inlinable
public init(_ 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
public struct DropWhileSequence<Base: Sequence> {
public typealias Element = Base.Element

@usableFromInline
internal var _iterator: Base.Iterator
@usableFromInline
internal var _nextElement: Element?

@inlinable
internal init(iterator: Base.Iterator, predicate: (Element) throws -> Bool) rethrows {
_iterator = iterator
_nextElement = _iterator.next()

while let x = _nextElement, try predicate(x) {
_nextElement = _iterator.next()
}
}

@inlinable
internal init(_ base: Base, predicate: (Element) throws -> Bool) rethrows {
self = try DropWhileSequence(iterator: base.makeIterator(), predicate: predicate)
}
}

Functions

suffix(_ maxLength: Int)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/// 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 func suffix(_ maxLength: Int) -> [Element] {
_Precondition(maxLength >= 0, "Can't take a suffix of negative length from a sequence")
guard maxLength != 0 else { 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 in self {
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]
return Array(rotated)
} else {
return Array(ringBuffer)
}
}

dropLast(_ k: Int = 1) -> [Element]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/// 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 func dropLast(_ k: Int = 1) -> [Element] {
_precondition(k >= 0, "Can't drop a negative number of elements from a sequence")
guard k != 0 else { return Array(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 in self {
// 当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
}
}
return Array(result)
}

elementsEqual

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
extension Sequence where Element: 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
public func elementsEqual<OtherSequence: Sequence>(
_ other: OtherSequence
)
-> Bool where OtherSequence.Element == Element {

return self.elementsEqual(other, by: ==)
}
}

flatMap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
extension Sequence {
/// 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
public func flatMap<SegmentOfResult: Sequence>(
_ transform: (Element)
throws -> SegmentOfResult

) rethrows -> [SegmentOfResult.Element] {
var result: [SegmentOfResult.Element] = []
for element in self {
/// 有别于map的地方
result.append(contentsOf: try transform(element))
}
return result
}
}

compactMap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
extension Sequence {
/// 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
public func compactMap<ElementOfResult>(
_ transform: (Element)
throws -> ElementOfResult?

) rethrows -> [ElementOfResult] {
return try _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)
public func _compactMap<ElementOfResult>(
_ transform: (Element)
throws -> ElementOfResult?

) rethrows -> [ElementOfResult] {
var result: [ElementOfResult] = []
for element in self {
/// 与map的区别
if let newElement = try transform(element) {
result.append(newElement)
}
}
return result
}
}

Reading Note of Book: Deep Work

Chapter One - Deep work is valuable:

Two Core Abilities for Thriving in the New Economy

  1. The ability to quickly master hard things.
  2. 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.