├── .gitignore
├── LICENSE-THREADLY.txt
├── LICENSE.txt
├── README.md
├── docs
├── Classes.html
├── Classes
│ ├── Collector.html
│ ├── Imitator.html
│ ├── Sink.html
│ ├── Stream.html
│ └── Subscription.html
├── Functions.html
├── badge.svg
├── css
│ ├── highlight.css
│ └── jazzy.css
├── docsets
│ ├── froop.docset
│ │ └── Contents
│ │ │ ├── Info.plist
│ │ │ └── Resources
│ │ │ ├── Documents
│ │ │ ├── Classes.html
│ │ │ ├── Classes
│ │ │ │ ├── Collector.html
│ │ │ │ ├── Imitator.html
│ │ │ │ ├── Sink.html
│ │ │ │ ├── Stream.html
│ │ │ │ └── Subscription.html
│ │ │ ├── Functions.html
│ │ │ ├── css
│ │ │ │ ├── highlight.css
│ │ │ │ └── jazzy.css
│ │ │ ├── img
│ │ │ │ ├── carat.png
│ │ │ │ ├── dash.png
│ │ │ │ └── gh.png
│ │ │ ├── index.html
│ │ │ ├── js
│ │ │ │ ├── jazzy.js
│ │ │ │ └── jquery.min.js
│ │ │ └── search.json
│ │ │ └── docSet.dsidx
│ └── froop.tgz
├── img
│ ├── carat.png
│ ├── dash.png
│ └── gh.png
├── index.html
├── js
│ ├── jazzy.js
│ └── jquery.min.js
├── search.json
└── undocumented.json
├── froop.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── xcshareddata
│ ├── xcbaselines
│ └── 5B891BFD2222EC47002F31C6.xcbaseline
│ │ ├── C6951AF0-5BDC-4962-A4A0-BEC937992614.plist
│ │ └── Info.plist
│ └── xcschemes
│ └── froop.xcscheme
├── froop
├── Info.plist
├── Threadly.swift
├── froop.h
└── froop.swift
├── froopTests
├── Info.plist
└── froopTests.swift
└── gen-docs.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData/
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata/
19 |
20 | ## Other
21 | *.moved-aside
22 | *.xccheckout
23 | *.xcscmblueprint
24 |
25 | ## Obj-C/Swift specific
26 | *.hmap
27 | *.ipa
28 | *.dSYM.zip
29 | *.dSYM
30 |
31 | ## Playgrounds
32 | timeline.xctimeline
33 | playground.xcworkspace
34 |
35 | # Swift Package Manager
36 | #
37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
38 | # Packages/
39 | # Package.pins
40 | # Package.resolved
41 | .build/
42 |
43 | # CocoaPods
44 | #
45 | # We recommend against adding the Pods directory to your .gitignore. However
46 | # you should judge for yourself, the pros and cons are mentioned at:
47 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
48 | #
49 | # Pods/
50 | #
51 | # Add this line if you want to avoid checking in source code from the Xcode workspace
52 | # *.xcworkspace
53 |
54 | # Carthage
55 | #
56 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
57 | # Carthage/Checkouts
58 |
59 | Carthage/Build
60 |
61 | # fastlane
62 | #
63 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
64 | # screenshots whenever they are needed.
65 | # For more information about the recommended setup visit:
66 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
67 |
68 | fastlane/report.xml
69 | fastlane/Preview.html
70 | fastlane/screenshots/**/*.png
71 | fastlane/test_output
72 |
73 | # Code Injection
74 | #
75 | # After new code Injection tools there's a generated folder /iOSInjectionProject
76 | # https://github.com/johnno1962/injectionforxcode
77 |
78 | iOSInjectionProject/
79 | # Xcode
80 | #
81 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
82 |
83 | ## User settings
84 | xcuserdata/
85 |
86 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
87 | *.xcscmblueprint
88 | *.xccheckout
89 |
90 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
91 | build/
92 | DerivedData/
93 | *.moved-aside
94 | *.pbxuser
95 | !default.pbxuser
96 | *.mode1v3
97 | !default.mode1v3
98 | *.mode2v3
99 | !default.mode2v3
100 | *.perspectivev3
101 | !default.perspectivev3
102 |
--------------------------------------------------------------------------------
/LICENSE-THREADLY.txt:
--------------------------------------------------------------------------------
1 | // Threadly.swift
2 | // Threadly
3 | //
4 | // The MIT License (MIT)
5 | //
6 | // Copyright (c) 2017 Nikolai Vazquez
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2019 Lookback Inc
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | SOFTWARE.
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | froop for swift
2 | ===============
3 |
4 | Functional reactive stream library for swift
5 |
6 | * Small (~20 operations)
7 | * Synchronous
8 | * No dependencies
9 | * Is FRP (ha!)
10 |
11 | ## Generate docs
12 |
13 | ```bash
14 | $ sudo gem install jazzy
15 | $ ./gen-docs.sh
16 | ```
17 |
18 | ## License
19 |
20 | See `LICENSE.txt` and for threadly see `LICENSE-THREADLY.txt`.
21 |
--------------------------------------------------------------------------------
/docs/Classes.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Classes Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
22 |
23 | froop Reference
24 |
25 | Classes Reference
26 |
27 |
28 |
29 |
82 |
83 |
84 |
85 | Classes
86 | The following classes are available globally.
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | Stream
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
Stream of vaules over time. Typically created by a Sink.
106 |
let sink = Sink < Int > ()
107 |
108 | let stream = sink . stream ()
109 | let double = stream . map () { $0 * 2 }
110 |
111 | sink . update ( 0 )
112 | sink . update ( 1 )
113 | ...
114 |
115 |
116 |
For some detailed notes on how a combinator is structured for ARC and thread
117 | safety, see the source code for the .map()
function. All operations follow
118 | a similar pattern.
119 |
120 |
See more
121 |
122 |
123 |
Declaration
124 |
125 |
Swift
126 |
public class Stream < T >
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
141 |
142 |
143 |
144 |
145 |
146 |
Specialization of Stream that has memory . Memory means that any
147 | new listener added will straight away get the last value that went through the stream.
148 |
149 |
150 |
151 |
Declaration
152 |
153 |
Swift
154 |
public class MemoryStream < T > : Stream < T >
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 | Sink
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
The originator of a stream of values.
175 |
let sink = Sink < Int > ()
176 |
177 | let stream = sink . stream ()
178 |
179 | ...
180 | sink . update ( 0 )
181 | sink . update ( 1 )
182 | sink . end ()
183 |
184 |
185 |
See more
186 |
187 |
188 |
Declaration
189 |
190 |
Swift
191 |
public class Sink < T >
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 | Collector
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
Helper to collect values from a stream. Mainly useful for tests.
212 |
213 |
See more
214 |
215 |
216 |
Declaration
217 |
218 |
Swift
219 |
public class Collector < T >
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
234 |
235 |
236 |
237 |
238 |
239 |
Subscriptions are receipts to the Stream.subscribe()
operation. They
240 | can be used to unsubscribe.
241 |
let sink = Sink < Int > ()
242 |
243 | let sub = sink . stream () . subscribe () { print ( " \( $0 ) " ) }
244 |
245 | sink . update ( 0 )
246 | sub . unsubscribe ()
247 | sink . update ( 1 ) // not received
248 |
249 |
250 |
See more
251 |
252 |
253 |
Declaration
254 |
255 |
Swift
256 |
public class Subscription < T >
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 | Imitator
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
Imitators are used to create cyclic streams. The imitator is an originator
277 | of a stream at the same time as it imitates some other stream further down
278 | the code.
279 |
280 |
Here’s a bad idea illustrating the usage:
281 |
let imitator = Imitator < Int > () stream of int
282 |
283 | let x = imitator . stream () . map () { $0 + 1 } // use imitator stream
284 | let y : Stream < Int > = ...
285 |
286 | let m = Stream . merge ( x , y ) // merge imiator with other stream
287 |
288 | imitator . imitate ( m ) // cycle all m up to imitator, this can only be done once
289 |
290 | // NB. This is a BAD IDEA, beacuse it causes an endless loop. Imitators must
291 | // be used with care to not spin out of control.
292 |
293 |
294 |
See more
295 |
296 |
297 |
Declaration
298 |
299 |
Swift
300 |
public class Imitator < T >
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
315 |
316 |
317 |
318 |
319 |
320 |
--------------------------------------------------------------------------------
/docs/Classes/Collector.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Collector Class Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
22 |
23 | froop Reference
24 |
25 | Collector Class Reference
26 |
27 |
28 |
29 |
82 |
83 |
84 |
85 | Collector
86 |
87 |
88 |
public class Collector < T >
89 |
90 |
91 |
92 | Helper to collect values from a stream. Mainly useful for tests.
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 | wait()
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
Stall the thread and wait for the stream this collector works off to end.
112 |
113 |
114 |
115 |
Declaration
116 |
117 |
Swift
118 |
public func wait () -> [ T ]
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 | take()
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
Take whatever values are in the collector without waiting for
139 | the stream to end.
140 |
141 |
142 |
143 |
Declaration
144 |
145 |
Swift
146 |
public func take () -> [ T ]
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
161 |
162 |
163 |
164 |
165 |
166 |
--------------------------------------------------------------------------------
/docs/Classes/Imitator.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Imitator Class Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
22 |
23 | froop Reference
24 |
25 | Imitator Class Reference
26 |
27 |
28 |
29 |
82 |
83 |
84 |
85 | Imitator
86 |
87 |
88 |
public class Imitator < T >
89 |
90 |
91 |
92 | Imitators are used to create cyclic streams. The imitator is an originator
93 | of a stream at the same time as it imitates some other stream further down
94 | the code.
95 |
96 | Here’s a bad idea illustrating the usage:
97 | let imitator = Imitator < Int > () stream of int
98 |
99 | let x = imitator . stream () . map () { $0 + 1 } // use imitator stream
100 | let y : Stream < Int > = ...
101 |
102 | let m = Stream . merge ( x , y ) // merge imiator with other stream
103 |
104 | imitator . imitate ( m ) // cycle all m up to imitator, this can only be done once
105 |
106 | // NB. This is a BAD IDEA, beacuse it causes an endless loop. Imitators must
107 | // be used with care to not spin out of control.
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 | stream()
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
Get a stream from this imitator. Can be used multiple times and each instance
128 | will be backed by the same imitator.
129 |
130 |
131 |
132 |
Declaration
133 |
134 |
Swift
135 |
public func stream () -> Stream < T >
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
150 |
151 |
152 |
153 |
154 |
155 |
Start imitating another stream. This can be called exactly once.
156 | Repeated calls will fatalError
.
157 |
158 |
159 |
160 |
Declaration
161 |
162 |
Swift
163 |
public func imitate ( other : Stream < T > )
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
178 |
179 |
180 |
181 |
182 |
183 |
--------------------------------------------------------------------------------
/docs/Classes/Sink.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Sink Class Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
22 |
23 | froop Reference
24 |
25 | Sink Class Reference
26 |
27 |
28 |
29 |
82 |
83 |
84 |
85 | Sink
86 |
87 |
88 |
public class Sink < T >
89 |
90 |
91 |
92 | The originator of a stream of values.
93 | let sink = Sink < Int > ()
94 |
95 | let stream = sink . stream ()
96 |
97 | ...
98 | sink . update ( 0 )
99 | sink . update ( 1 )
100 | sink . end ()
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 | init()
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
Create a new sink.
121 |
122 |
123 |
124 |
Declaration
125 |
126 |
Swift
127 |
public init ()
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 | stream()
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
Get a stream from this sink. Can be used multiple times and each instance
148 | will be backed by the same sink.
149 |
150 |
151 |
152 |
Declaration
153 |
154 |
Swift
155 |
public func stream () -> Stream < T >
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
170 |
171 |
172 |
173 |
174 |
175 |
Update a value into the sink and all connected streams.
176 |
177 |
178 |
179 |
Declaration
180 |
181 |
Swift
182 |
public func update ( _ t : T )
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 | end()
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
End this sink. No more values can be sent after this.
203 |
204 |
205 |
206 |
Declaration
207 |
208 |
Swift
209 |
public func end ()
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
224 |
225 |
226 |
227 |
228 |
229 |
--------------------------------------------------------------------------------
/docs/Classes/Subscription.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Subscription Class Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
22 |
23 | froop Reference
24 |
25 | Subscription Class Reference
26 |
27 |
28 |
29 |
82 |
83 |
84 |
85 | Subscription
86 |
87 |
88 |
public class Subscription < T >
89 |
90 |
91 |
92 | Subscriptions are receipts to the Stream.subscribe()
operation. They
93 | can be used to unsubscribe.
94 | let sink = Sink < Int > ()
95 |
96 | let sub = sink . stream () . subscribe () { print ( " \( $0 ) " ) }
97 |
98 | sink . update ( 0 )
99 | sub . unsubscribe ()
100 | sink . update ( 1 ) // not received
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
115 |
116 |
117 |
118 |
119 |
120 |
Unsubscribe from further updates.
121 |
122 |
123 |
124 |
Declaration
125 |
126 |
Swift
127 |
public func unsubscribe ()
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
142 |
143 |
144 |
145 |
146 |
147 |
--------------------------------------------------------------------------------
/docs/badge.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | documentation
17 |
18 |
19 | documentation
20 |
21 |
22 | 100%
23 |
24 |
25 | 100%
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/docs/css/highlight.css:
--------------------------------------------------------------------------------
1 | /* Credit to https://gist.github.com/wataru420/2048287 */
2 | .highlight {
3 | /* Comment */
4 | /* Error */
5 | /* Keyword */
6 | /* Operator */
7 | /* Comment.Multiline */
8 | /* Comment.Preproc */
9 | /* Comment.Single */
10 | /* Comment.Special */
11 | /* Generic.Deleted */
12 | /* Generic.Deleted.Specific */
13 | /* Generic.Emph */
14 | /* Generic.Error */
15 | /* Generic.Heading */
16 | /* Generic.Inserted */
17 | /* Generic.Inserted.Specific */
18 | /* Generic.Output */
19 | /* Generic.Prompt */
20 | /* Generic.Strong */
21 | /* Generic.Subheading */
22 | /* Generic.Traceback */
23 | /* Keyword.Constant */
24 | /* Keyword.Declaration */
25 | /* Keyword.Pseudo */
26 | /* Keyword.Reserved */
27 | /* Keyword.Type */
28 | /* Literal.Number */
29 | /* Literal.String */
30 | /* Name.Attribute */
31 | /* Name.Builtin */
32 | /* Name.Class */
33 | /* Name.Constant */
34 | /* Name.Entity */
35 | /* Name.Exception */
36 | /* Name.Function */
37 | /* Name.Namespace */
38 | /* Name.Tag */
39 | /* Name.Variable */
40 | /* Operator.Word */
41 | /* Text.Whitespace */
42 | /* Literal.Number.Float */
43 | /* Literal.Number.Hex */
44 | /* Literal.Number.Integer */
45 | /* Literal.Number.Oct */
46 | /* Literal.String.Backtick */
47 | /* Literal.String.Char */
48 | /* Literal.String.Doc */
49 | /* Literal.String.Double */
50 | /* Literal.String.Escape */
51 | /* Literal.String.Heredoc */
52 | /* Literal.String.Interpol */
53 | /* Literal.String.Other */
54 | /* Literal.String.Regex */
55 | /* Literal.String.Single */
56 | /* Literal.String.Symbol */
57 | /* Name.Builtin.Pseudo */
58 | /* Name.Variable.Class */
59 | /* Name.Variable.Global */
60 | /* Name.Variable.Instance */
61 | /* Literal.Number.Integer.Long */ }
62 | .highlight .c {
63 | color: #999988;
64 | font-style: italic; }
65 | .highlight .err {
66 | color: #a61717;
67 | background-color: #e3d2d2; }
68 | .highlight .k {
69 | color: #000000;
70 | font-weight: bold; }
71 | .highlight .o {
72 | color: #000000;
73 | font-weight: bold; }
74 | .highlight .cm {
75 | color: #999988;
76 | font-style: italic; }
77 | .highlight .cp {
78 | color: #999999;
79 | font-weight: bold; }
80 | .highlight .c1 {
81 | color: #999988;
82 | font-style: italic; }
83 | .highlight .cs {
84 | color: #999999;
85 | font-weight: bold;
86 | font-style: italic; }
87 | .highlight .gd {
88 | color: #000000;
89 | background-color: #ffdddd; }
90 | .highlight .gd .x {
91 | color: #000000;
92 | background-color: #ffaaaa; }
93 | .highlight .ge {
94 | color: #000000;
95 | font-style: italic; }
96 | .highlight .gr {
97 | color: #aa0000; }
98 | .highlight .gh {
99 | color: #999999; }
100 | .highlight .gi {
101 | color: #000000;
102 | background-color: #ddffdd; }
103 | .highlight .gi .x {
104 | color: #000000;
105 | background-color: #aaffaa; }
106 | .highlight .go {
107 | color: #888888; }
108 | .highlight .gp {
109 | color: #555555; }
110 | .highlight .gs {
111 | font-weight: bold; }
112 | .highlight .gu {
113 | color: #aaaaaa; }
114 | .highlight .gt {
115 | color: #aa0000; }
116 | .highlight .kc {
117 | color: #000000;
118 | font-weight: bold; }
119 | .highlight .kd {
120 | color: #000000;
121 | font-weight: bold; }
122 | .highlight .kp {
123 | color: #000000;
124 | font-weight: bold; }
125 | .highlight .kr {
126 | color: #000000;
127 | font-weight: bold; }
128 | .highlight .kt {
129 | color: #445588; }
130 | .highlight .m {
131 | color: #009999; }
132 | .highlight .s {
133 | color: #d14; }
134 | .highlight .na {
135 | color: #008080; }
136 | .highlight .nb {
137 | color: #0086B3; }
138 | .highlight .nc {
139 | color: #445588;
140 | font-weight: bold; }
141 | .highlight .no {
142 | color: #008080; }
143 | .highlight .ni {
144 | color: #800080; }
145 | .highlight .ne {
146 | color: #990000;
147 | font-weight: bold; }
148 | .highlight .nf {
149 | color: #990000; }
150 | .highlight .nn {
151 | color: #555555; }
152 | .highlight .nt {
153 | color: #000080; }
154 | .highlight .nv {
155 | color: #008080; }
156 | .highlight .ow {
157 | color: #000000;
158 | font-weight: bold; }
159 | .highlight .w {
160 | color: #bbbbbb; }
161 | .highlight .mf {
162 | color: #009999; }
163 | .highlight .mh {
164 | color: #009999; }
165 | .highlight .mi {
166 | color: #009999; }
167 | .highlight .mo {
168 | color: #009999; }
169 | .highlight .sb {
170 | color: #d14; }
171 | .highlight .sc {
172 | color: #d14; }
173 | .highlight .sd {
174 | color: #d14; }
175 | .highlight .s2 {
176 | color: #d14; }
177 | .highlight .se {
178 | color: #d14; }
179 | .highlight .sh {
180 | color: #d14; }
181 | .highlight .si {
182 | color: #d14; }
183 | .highlight .sx {
184 | color: #d14; }
185 | .highlight .sr {
186 | color: #009926; }
187 | .highlight .s1 {
188 | color: #d14; }
189 | .highlight .ss {
190 | color: #990073; }
191 | .highlight .bp {
192 | color: #999999; }
193 | .highlight .vc {
194 | color: #008080; }
195 | .highlight .vg {
196 | color: #008080; }
197 | .highlight .vi {
198 | color: #008080; }
199 | .highlight .il {
200 | color: #009999; }
201 |
--------------------------------------------------------------------------------
/docs/css/jazzy.css:
--------------------------------------------------------------------------------
1 | html, body, div, span, h1, h3, h4, p, a, code, em, img, ul, li, table, tbody, tr, td {
2 | background: transparent;
3 | border: 0;
4 | margin: 0;
5 | outline: 0;
6 | padding: 0;
7 | vertical-align: baseline; }
8 |
9 | body {
10 | background-color: #f2f2f2;
11 | font-family: Helvetica, freesans, Arial, sans-serif;
12 | font-size: 14px;
13 | -webkit-font-smoothing: subpixel-antialiased;
14 | word-wrap: break-word; }
15 |
16 | h1, h2, h3 {
17 | margin-top: 0.8em;
18 | margin-bottom: 0.3em;
19 | font-weight: 100;
20 | color: black; }
21 |
22 | h1 {
23 | font-size: 2.5em; }
24 |
25 | h2 {
26 | font-size: 2em;
27 | border-bottom: 1px solid #e2e2e2; }
28 |
29 | h4 {
30 | font-size: 13px;
31 | line-height: 1.5;
32 | margin-top: 21px; }
33 |
34 | h5 {
35 | font-size: 1.1em; }
36 |
37 | h6 {
38 | font-size: 1.1em;
39 | color: #777; }
40 |
41 | .section-name {
42 | color: gray;
43 | display: block;
44 | font-family: Helvetica;
45 | font-size: 22px;
46 | font-weight: 100;
47 | margin-bottom: 15px; }
48 |
49 | pre, code {
50 | font: 0.95em Menlo, monospace;
51 | color: #777;
52 | word-wrap: normal; }
53 |
54 | p code, li code {
55 | background-color: #eee;
56 | padding: 2px 4px;
57 | border-radius: 4px; }
58 |
59 | a {
60 | color: #0088cc;
61 | text-decoration: none; }
62 |
63 | ul {
64 | padding-left: 15px; }
65 |
66 | li {
67 | line-height: 1.8em; }
68 |
69 | img {
70 | max-width: 100%; }
71 |
72 | blockquote {
73 | margin-left: 0;
74 | padding: 0 10px;
75 | border-left: 4px solid #ccc; }
76 |
77 | .content-wrapper {
78 | margin: 0 auto;
79 | width: 980px; }
80 |
81 | header {
82 | font-size: 0.85em;
83 | line-height: 26px;
84 | background-color: #414141;
85 | position: fixed;
86 | width: 100%;
87 | z-index: 1; }
88 | header img {
89 | padding-right: 6px;
90 | vertical-align: -4px;
91 | height: 16px; }
92 | header a {
93 | color: #fff; }
94 | header p {
95 | float: left;
96 | color: #999; }
97 | header .header-right {
98 | float: right;
99 | margin-left: 16px; }
100 |
101 | #breadcrumbs {
102 | background-color: #f2f2f2;
103 | height: 27px;
104 | padding-top: 17px;
105 | position: fixed;
106 | width: 100%;
107 | z-index: 1;
108 | margin-top: 26px; }
109 | #breadcrumbs #carat {
110 | height: 10px;
111 | margin: 0 5px; }
112 |
113 | .sidebar {
114 | background-color: #f9f9f9;
115 | border: 1px solid #e2e2e2;
116 | overflow-y: auto;
117 | overflow-x: hidden;
118 | position: fixed;
119 | top: 70px;
120 | bottom: 0;
121 | width: 230px;
122 | word-wrap: normal; }
123 |
124 | .nav-groups {
125 | list-style-type: none;
126 | background: #fff;
127 | padding-left: 0; }
128 |
129 | .nav-group-name {
130 | border-bottom: 1px solid #e2e2e2;
131 | font-size: 1.1em;
132 | font-weight: 100;
133 | padding: 15px 0 15px 20px; }
134 | .nav-group-name > a {
135 | color: #333; }
136 |
137 | .nav-group-tasks {
138 | margin-top: 5px; }
139 |
140 | .nav-group-task {
141 | font-size: 0.9em;
142 | list-style-type: none;
143 | white-space: nowrap; }
144 | .nav-group-task a {
145 | color: #888; }
146 |
147 | .main-content {
148 | background-color: #fff;
149 | border: 1px solid #e2e2e2;
150 | margin-left: 246px;
151 | position: absolute;
152 | overflow: hidden;
153 | padding-bottom: 20px;
154 | top: 70px;
155 | width: 734px; }
156 | .main-content p, .main-content a, .main-content code, .main-content em, .main-content ul, .main-content table, .main-content blockquote {
157 | margin-bottom: 1em; }
158 | .main-content p {
159 | line-height: 1.8em; }
160 | .main-content section .section:first-child {
161 | margin-top: 0;
162 | padding-top: 0; }
163 | .main-content section .task-group-section .task-group:first-of-type {
164 | padding-top: 10px; }
165 | .main-content section .task-group-section .task-group:first-of-type .section-name {
166 | padding-top: 15px; }
167 | .main-content section .heading:before {
168 | content: "";
169 | display: block;
170 | padding-top: 70px;
171 | margin: -70px 0 0; }
172 |
173 | .section {
174 | padding: 0 25px; }
175 |
176 | .highlight {
177 | background-color: #eee;
178 | padding: 10px 12px;
179 | border: 1px solid #e2e2e2;
180 | border-radius: 4px;
181 | overflow-x: auto; }
182 |
183 | .declaration .highlight {
184 | overflow-x: initial;
185 | padding: 0 40px 40px 0;
186 | margin-bottom: -25px;
187 | background-color: transparent;
188 | border: none; }
189 |
190 | .section-name {
191 | margin: 0;
192 | margin-left: 18px; }
193 |
194 | .task-group-section {
195 | padding-left: 6px;
196 | border-top: 1px solid #e2e2e2; }
197 |
198 | .task-group {
199 | padding-top: 0px; }
200 |
201 | .task-name-container a[name]:before {
202 | content: "";
203 | display: block;
204 | padding-top: 70px;
205 | margin: -70px 0 0; }
206 |
207 | .item {
208 | padding-top: 8px;
209 | width: 100%;
210 | list-style-type: none; }
211 | .item a[name]:before {
212 | content: "";
213 | display: block;
214 | padding-top: 70px;
215 | margin: -70px 0 0; }
216 | .item code {
217 | background-color: transparent;
218 | padding: 0; }
219 | .item .token, .item .direct-link {
220 | padding-left: 3px;
221 | margin-left: 15px;
222 | font-size: 11.9px; }
223 | .item .discouraged {
224 | text-decoration: line-through; }
225 | .item .declaration-note {
226 | font-size: .85em;
227 | color: gray;
228 | font-style: italic; }
229 |
230 | .pointer-container {
231 | border-bottom: 1px solid #e2e2e2;
232 | left: -23px;
233 | padding-bottom: 13px;
234 | position: relative;
235 | width: 110%; }
236 |
237 | .pointer {
238 | background: #f9f9f9;
239 | border-left: 1px solid #e2e2e2;
240 | border-top: 1px solid #e2e2e2;
241 | height: 12px;
242 | left: 21px;
243 | top: -7px;
244 | -webkit-transform: rotate(45deg);
245 | -moz-transform: rotate(45deg);
246 | -o-transform: rotate(45deg);
247 | transform: rotate(45deg);
248 | position: absolute;
249 | width: 12px; }
250 |
251 | .height-container {
252 | display: none;
253 | left: -25px;
254 | padding: 0 25px;
255 | position: relative;
256 | width: 100%;
257 | overflow: hidden; }
258 | .height-container .section {
259 | background: #f9f9f9;
260 | border-bottom: 1px solid #e2e2e2;
261 | left: -25px;
262 | position: relative;
263 | width: 100%;
264 | padding-top: 10px;
265 | padding-bottom: 5px; }
266 |
267 | .aside, .language {
268 | padding: 6px 12px;
269 | margin: 12px 0;
270 | border-left: 5px solid #dddddd;
271 | overflow-y: hidden; }
272 | .aside .aside-title, .language .aside-title {
273 | font-size: 9px;
274 | letter-spacing: 2px;
275 | text-transform: uppercase;
276 | padding-bottom: 0;
277 | margin: 0;
278 | color: #aaa;
279 | -webkit-user-select: none; }
280 | .aside p:last-child, .language p:last-child {
281 | margin-bottom: 0; }
282 |
283 | .language {
284 | border-left: 5px solid #cde9f4; }
285 | .language .aside-title {
286 | color: #4b8afb; }
287 |
288 | .aside-warning, .aside-deprecated, .aside-unavailable {
289 | border-left: 5px solid #ff6666; }
290 | .aside-warning .aside-title, .aside-deprecated .aside-title, .aside-unavailable .aside-title {
291 | color: #ff0000; }
292 |
293 | .graybox {
294 | border-collapse: collapse;
295 | width: 100%; }
296 | .graybox p {
297 | margin: 0;
298 | word-break: break-word;
299 | min-width: 50px; }
300 | .graybox td {
301 | border: 1px solid #e2e2e2;
302 | padding: 5px 25px 5px 10px;
303 | vertical-align: middle; }
304 | .graybox tr td:first-of-type {
305 | text-align: right;
306 | padding: 7px;
307 | vertical-align: top;
308 | word-break: normal;
309 | width: 40px; }
310 |
311 | .slightly-smaller {
312 | font-size: 0.9em; }
313 |
314 | #footer {
315 | position: relative;
316 | top: 10px;
317 | bottom: 0px;
318 | margin-left: 25px; }
319 | #footer p {
320 | margin: 0;
321 | color: #aaa;
322 | font-size: 0.8em; }
323 |
324 | html.dash header, html.dash #breadcrumbs, html.dash .sidebar {
325 | display: none; }
326 | html.dash .main-content {
327 | width: 980px;
328 | margin-left: 0;
329 | border: none;
330 | width: 100%;
331 | top: 0;
332 | padding-bottom: 0; }
333 | html.dash .height-container {
334 | display: block; }
335 | html.dash .item .token {
336 | margin-left: 0; }
337 | html.dash .content-wrapper {
338 | width: auto; }
339 | html.dash #footer {
340 | position: static; }
341 |
--------------------------------------------------------------------------------
/docs/docsets/froop.docset/Contents/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleIdentifier
6 | com.jazzy.froop
7 | CFBundleName
8 | froop
9 | DocSetPlatformFamily
10 | froop
11 | isDashDocset
12 |
13 | dashIndexFilePath
14 | index.html
15 | isJavaScriptEnabled
16 |
17 | DashDocSetFamily
18 | dashtoc
19 |
20 |
21 |
--------------------------------------------------------------------------------
/docs/docsets/froop.docset/Contents/Resources/Documents/Classes.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Classes Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
22 |
23 | froop Reference
24 |
25 | Classes Reference
26 |
27 |
28 |
29 |
82 |
83 |
84 |
85 | Classes
86 | The following classes are available globally.
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | Stream
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
Stream of vaules over time. Typically created by a Sink.
106 |
let sink = Sink < Int > ()
107 |
108 | let stream = sink . stream ()
109 | let double = stream . map () { $0 * 2 }
110 |
111 | sink . update ( 0 )
112 | sink . update ( 1 )
113 | ...
114 |
115 |
116 |
For some detailed notes on how a combinator is structured for ARC and thread
117 | safety, see the source code for the .map()
function. All operations follow
118 | a similar pattern.
119 |
120 |
See more
121 |
122 |
123 |
Declaration
124 |
125 |
Swift
126 |
public class Stream < T >
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
141 |
142 |
143 |
144 |
145 |
146 |
Specialization of Stream that has memory . Memory means that any
147 | new listener added will straight away get the last value that went through the stream.
148 |
149 |
150 |
151 |
Declaration
152 |
153 |
Swift
154 |
public class MemoryStream < T > : Stream < T >
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 | Sink
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
The originator of a stream of values.
175 |
let sink = Sink < Int > ()
176 |
177 | let stream = sink . stream ()
178 |
179 | ...
180 | sink . update ( 0 )
181 | sink . update ( 1 )
182 | sink . end ()
183 |
184 |
185 |
See more
186 |
187 |
188 |
Declaration
189 |
190 |
Swift
191 |
public class Sink < T >
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 | Collector
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
Helper to collect values from a stream. Mainly useful for tests.
212 |
213 |
See more
214 |
215 |
216 |
Declaration
217 |
218 |
Swift
219 |
public class Collector < T >
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
234 |
235 |
236 |
237 |
238 |
239 |
Subscriptions are receipts to the Stream.subscribe()
operation. They
240 | can be used to unsubscribe.
241 |
let sink = Sink < Int > ()
242 |
243 | let sub = sink . stream () . subscribe () { print ( " \( $0 ) " ) }
244 |
245 | sink . update ( 0 )
246 | sub . unsubscribe ()
247 | sink . update ( 1 ) // not received
248 |
249 |
250 |
See more
251 |
252 |
253 |
Declaration
254 |
255 |
Swift
256 |
public class Subscription < T >
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 | Imitator
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
Imitators are used to create cyclic streams. The imitator is an originator
277 | of a stream at the same time as it imitates some other stream further down
278 | the code.
279 |
280 |
Here’s a bad idea illustrating the usage:
281 |
let imitator = Imitator < Int > () stream of int
282 |
283 | let x = imitator . stream () . map () { $0 + 1 } // use imitator stream
284 | let y : Stream < Int > = ...
285 |
286 | let m = Stream . merge ( x , y ) // merge imiator with other stream
287 |
288 | imitator . imitate ( m ) // cycle all m up to imitator, this can only be done once
289 |
290 | // NB. This is a BAD IDEA, beacuse it causes an endless loop. Imitators must
291 | // be used with care to not spin out of control.
292 |
293 |
294 |
See more
295 |
296 |
297 |
Declaration
298 |
299 |
Swift
300 |
public class Imitator < T >
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
315 |
316 |
317 |
318 |
319 |
320 |
--------------------------------------------------------------------------------
/docs/docsets/froop.docset/Contents/Resources/Documents/Classes/Collector.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Collector Class Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
22 |
23 | froop Reference
24 |
25 | Collector Class Reference
26 |
27 |
28 |
29 |
82 |
83 |
84 |
85 | Collector
86 |
87 |
88 |
public class Collector < T >
89 |
90 |
91 |
92 | Helper to collect values from a stream. Mainly useful for tests.
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 | wait()
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
Stall the thread and wait for the stream this collector works off to end.
112 |
113 |
114 |
115 |
Declaration
116 |
117 |
Swift
118 |
public func wait () -> [ T ]
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 | take()
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
Take whatever values are in the collector without waiting for
139 | the stream to end.
140 |
141 |
142 |
143 |
Declaration
144 |
145 |
Swift
146 |
public func take () -> [ T ]
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
161 |
162 |
163 |
164 |
165 |
166 |
--------------------------------------------------------------------------------
/docs/docsets/froop.docset/Contents/Resources/Documents/Classes/Imitator.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Imitator Class Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
22 |
23 | froop Reference
24 |
25 | Imitator Class Reference
26 |
27 |
28 |
29 |
82 |
83 |
84 |
85 | Imitator
86 |
87 |
88 |
public class Imitator < T >
89 |
90 |
91 |
92 | Imitators are used to create cyclic streams. The imitator is an originator
93 | of a stream at the same time as it imitates some other stream further down
94 | the code.
95 |
96 | Here’s a bad idea illustrating the usage:
97 | let imitator = Imitator < Int > () stream of int
98 |
99 | let x = imitator . stream () . map () { $0 + 1 } // use imitator stream
100 | let y : Stream < Int > = ...
101 |
102 | let m = Stream . merge ( x , y ) // merge imiator with other stream
103 |
104 | imitator . imitate ( m ) // cycle all m up to imitator, this can only be done once
105 |
106 | // NB. This is a BAD IDEA, beacuse it causes an endless loop. Imitators must
107 | // be used with care to not spin out of control.
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 | stream()
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
Get a stream from this imitator. Can be used multiple times and each instance
128 | will be backed by the same imitator.
129 |
130 |
131 |
132 |
Declaration
133 |
134 |
Swift
135 |
public func stream () -> Stream < T >
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
150 |
151 |
152 |
153 |
154 |
155 |
Start imitating another stream. This can be called exactly once.
156 | Repeated calls will fatalError
.
157 |
158 |
159 |
160 |
Declaration
161 |
162 |
Swift
163 |
public func imitate ( other : Stream < T > )
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
178 |
179 |
180 |
181 |
182 |
183 |
--------------------------------------------------------------------------------
/docs/docsets/froop.docset/Contents/Resources/Documents/Classes/Sink.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Sink Class Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
22 |
23 | froop Reference
24 |
25 | Sink Class Reference
26 |
27 |
28 |
29 |
82 |
83 |
84 |
85 | Sink
86 |
87 |
88 |
public class Sink < T >
89 |
90 |
91 |
92 | The originator of a stream of values.
93 | let sink = Sink < Int > ()
94 |
95 | let stream = sink . stream ()
96 |
97 | ...
98 | sink . update ( 0 )
99 | sink . update ( 1 )
100 | sink . end ()
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 | init()
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
Create a new sink.
121 |
122 |
123 |
124 |
Declaration
125 |
126 |
Swift
127 |
public init ()
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 | stream()
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
Get a stream from this sink. Can be used multiple times and each instance
148 | will be backed by the same sink.
149 |
150 |
151 |
152 |
Declaration
153 |
154 |
Swift
155 |
public func stream () -> Stream < T >
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
170 |
171 |
172 |
173 |
174 |
175 |
Update a value into the sink and all connected streams.
176 |
177 |
178 |
179 |
Declaration
180 |
181 |
Swift
182 |
public func update ( _ t : T )
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 | end()
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
End this sink. No more values can be sent after this.
203 |
204 |
205 |
206 |
Declaration
207 |
208 |
Swift
209 |
public func end ()
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
224 |
225 |
226 |
227 |
228 |
229 |
--------------------------------------------------------------------------------
/docs/docsets/froop.docset/Contents/Resources/Documents/Classes/Subscription.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Subscription Class Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
22 |
23 | froop Reference
24 |
25 | Subscription Class Reference
26 |
27 |
28 |
29 |
82 |
83 |
84 |
85 | Subscription
86 |
87 |
88 |
public class Subscription < T >
89 |
90 |
91 |
92 | Subscriptions are receipts to the Stream.subscribe()
operation. They
93 | can be used to unsubscribe.
94 | let sink = Sink < Int > ()
95 |
96 | let sub = sink . stream () . subscribe () { print ( " \( $0 ) " ) }
97 |
98 | sink . update ( 0 )
99 | sub . unsubscribe ()
100 | sink . update ( 1 ) // not received
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
115 |
116 |
117 |
118 |
119 |
120 |
Unsubscribe from further updates.
121 |
122 |
123 |
124 |
Declaration
125 |
126 |
Swift
127 |
public func unsubscribe ()
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
142 |
143 |
144 |
145 |
146 |
147 |
--------------------------------------------------------------------------------
/docs/docsets/froop.docset/Contents/Resources/Documents/css/highlight.css:
--------------------------------------------------------------------------------
1 | /* Credit to https://gist.github.com/wataru420/2048287 */
2 | .highlight {
3 | /* Comment */
4 | /* Error */
5 | /* Keyword */
6 | /* Operator */
7 | /* Comment.Multiline */
8 | /* Comment.Preproc */
9 | /* Comment.Single */
10 | /* Comment.Special */
11 | /* Generic.Deleted */
12 | /* Generic.Deleted.Specific */
13 | /* Generic.Emph */
14 | /* Generic.Error */
15 | /* Generic.Heading */
16 | /* Generic.Inserted */
17 | /* Generic.Inserted.Specific */
18 | /* Generic.Output */
19 | /* Generic.Prompt */
20 | /* Generic.Strong */
21 | /* Generic.Subheading */
22 | /* Generic.Traceback */
23 | /* Keyword.Constant */
24 | /* Keyword.Declaration */
25 | /* Keyword.Pseudo */
26 | /* Keyword.Reserved */
27 | /* Keyword.Type */
28 | /* Literal.Number */
29 | /* Literal.String */
30 | /* Name.Attribute */
31 | /* Name.Builtin */
32 | /* Name.Class */
33 | /* Name.Constant */
34 | /* Name.Entity */
35 | /* Name.Exception */
36 | /* Name.Function */
37 | /* Name.Namespace */
38 | /* Name.Tag */
39 | /* Name.Variable */
40 | /* Operator.Word */
41 | /* Text.Whitespace */
42 | /* Literal.Number.Float */
43 | /* Literal.Number.Hex */
44 | /* Literal.Number.Integer */
45 | /* Literal.Number.Oct */
46 | /* Literal.String.Backtick */
47 | /* Literal.String.Char */
48 | /* Literal.String.Doc */
49 | /* Literal.String.Double */
50 | /* Literal.String.Escape */
51 | /* Literal.String.Heredoc */
52 | /* Literal.String.Interpol */
53 | /* Literal.String.Other */
54 | /* Literal.String.Regex */
55 | /* Literal.String.Single */
56 | /* Literal.String.Symbol */
57 | /* Name.Builtin.Pseudo */
58 | /* Name.Variable.Class */
59 | /* Name.Variable.Global */
60 | /* Name.Variable.Instance */
61 | /* Literal.Number.Integer.Long */ }
62 | .highlight .c {
63 | color: #999988;
64 | font-style: italic; }
65 | .highlight .err {
66 | color: #a61717;
67 | background-color: #e3d2d2; }
68 | .highlight .k {
69 | color: #000000;
70 | font-weight: bold; }
71 | .highlight .o {
72 | color: #000000;
73 | font-weight: bold; }
74 | .highlight .cm {
75 | color: #999988;
76 | font-style: italic; }
77 | .highlight .cp {
78 | color: #999999;
79 | font-weight: bold; }
80 | .highlight .c1 {
81 | color: #999988;
82 | font-style: italic; }
83 | .highlight .cs {
84 | color: #999999;
85 | font-weight: bold;
86 | font-style: italic; }
87 | .highlight .gd {
88 | color: #000000;
89 | background-color: #ffdddd; }
90 | .highlight .gd .x {
91 | color: #000000;
92 | background-color: #ffaaaa; }
93 | .highlight .ge {
94 | color: #000000;
95 | font-style: italic; }
96 | .highlight .gr {
97 | color: #aa0000; }
98 | .highlight .gh {
99 | color: #999999; }
100 | .highlight .gi {
101 | color: #000000;
102 | background-color: #ddffdd; }
103 | .highlight .gi .x {
104 | color: #000000;
105 | background-color: #aaffaa; }
106 | .highlight .go {
107 | color: #888888; }
108 | .highlight .gp {
109 | color: #555555; }
110 | .highlight .gs {
111 | font-weight: bold; }
112 | .highlight .gu {
113 | color: #aaaaaa; }
114 | .highlight .gt {
115 | color: #aa0000; }
116 | .highlight .kc {
117 | color: #000000;
118 | font-weight: bold; }
119 | .highlight .kd {
120 | color: #000000;
121 | font-weight: bold; }
122 | .highlight .kp {
123 | color: #000000;
124 | font-weight: bold; }
125 | .highlight .kr {
126 | color: #000000;
127 | font-weight: bold; }
128 | .highlight .kt {
129 | color: #445588; }
130 | .highlight .m {
131 | color: #009999; }
132 | .highlight .s {
133 | color: #d14; }
134 | .highlight .na {
135 | color: #008080; }
136 | .highlight .nb {
137 | color: #0086B3; }
138 | .highlight .nc {
139 | color: #445588;
140 | font-weight: bold; }
141 | .highlight .no {
142 | color: #008080; }
143 | .highlight .ni {
144 | color: #800080; }
145 | .highlight .ne {
146 | color: #990000;
147 | font-weight: bold; }
148 | .highlight .nf {
149 | color: #990000; }
150 | .highlight .nn {
151 | color: #555555; }
152 | .highlight .nt {
153 | color: #000080; }
154 | .highlight .nv {
155 | color: #008080; }
156 | .highlight .ow {
157 | color: #000000;
158 | font-weight: bold; }
159 | .highlight .w {
160 | color: #bbbbbb; }
161 | .highlight .mf {
162 | color: #009999; }
163 | .highlight .mh {
164 | color: #009999; }
165 | .highlight .mi {
166 | color: #009999; }
167 | .highlight .mo {
168 | color: #009999; }
169 | .highlight .sb {
170 | color: #d14; }
171 | .highlight .sc {
172 | color: #d14; }
173 | .highlight .sd {
174 | color: #d14; }
175 | .highlight .s2 {
176 | color: #d14; }
177 | .highlight .se {
178 | color: #d14; }
179 | .highlight .sh {
180 | color: #d14; }
181 | .highlight .si {
182 | color: #d14; }
183 | .highlight .sx {
184 | color: #d14; }
185 | .highlight .sr {
186 | color: #009926; }
187 | .highlight .s1 {
188 | color: #d14; }
189 | .highlight .ss {
190 | color: #990073; }
191 | .highlight .bp {
192 | color: #999999; }
193 | .highlight .vc {
194 | color: #008080; }
195 | .highlight .vg {
196 | color: #008080; }
197 | .highlight .vi {
198 | color: #008080; }
199 | .highlight .il {
200 | color: #009999; }
201 |
--------------------------------------------------------------------------------
/docs/docsets/froop.docset/Contents/Resources/Documents/css/jazzy.css:
--------------------------------------------------------------------------------
1 | html, body, div, span, h1, h3, h4, p, a, code, em, img, ul, li, table, tbody, tr, td {
2 | background: transparent;
3 | border: 0;
4 | margin: 0;
5 | outline: 0;
6 | padding: 0;
7 | vertical-align: baseline; }
8 |
9 | body {
10 | background-color: #f2f2f2;
11 | font-family: Helvetica, freesans, Arial, sans-serif;
12 | font-size: 14px;
13 | -webkit-font-smoothing: subpixel-antialiased;
14 | word-wrap: break-word; }
15 |
16 | h1, h2, h3 {
17 | margin-top: 0.8em;
18 | margin-bottom: 0.3em;
19 | font-weight: 100;
20 | color: black; }
21 |
22 | h1 {
23 | font-size: 2.5em; }
24 |
25 | h2 {
26 | font-size: 2em;
27 | border-bottom: 1px solid #e2e2e2; }
28 |
29 | h4 {
30 | font-size: 13px;
31 | line-height: 1.5;
32 | margin-top: 21px; }
33 |
34 | h5 {
35 | font-size: 1.1em; }
36 |
37 | h6 {
38 | font-size: 1.1em;
39 | color: #777; }
40 |
41 | .section-name {
42 | color: gray;
43 | display: block;
44 | font-family: Helvetica;
45 | font-size: 22px;
46 | font-weight: 100;
47 | margin-bottom: 15px; }
48 |
49 | pre, code {
50 | font: 0.95em Menlo, monospace;
51 | color: #777;
52 | word-wrap: normal; }
53 |
54 | p code, li code {
55 | background-color: #eee;
56 | padding: 2px 4px;
57 | border-radius: 4px; }
58 |
59 | a {
60 | color: #0088cc;
61 | text-decoration: none; }
62 |
63 | ul {
64 | padding-left: 15px; }
65 |
66 | li {
67 | line-height: 1.8em; }
68 |
69 | img {
70 | max-width: 100%; }
71 |
72 | blockquote {
73 | margin-left: 0;
74 | padding: 0 10px;
75 | border-left: 4px solid #ccc; }
76 |
77 | .content-wrapper {
78 | margin: 0 auto;
79 | width: 980px; }
80 |
81 | header {
82 | font-size: 0.85em;
83 | line-height: 26px;
84 | background-color: #414141;
85 | position: fixed;
86 | width: 100%;
87 | z-index: 1; }
88 | header img {
89 | padding-right: 6px;
90 | vertical-align: -4px;
91 | height: 16px; }
92 | header a {
93 | color: #fff; }
94 | header p {
95 | float: left;
96 | color: #999; }
97 | header .header-right {
98 | float: right;
99 | margin-left: 16px; }
100 |
101 | #breadcrumbs {
102 | background-color: #f2f2f2;
103 | height: 27px;
104 | padding-top: 17px;
105 | position: fixed;
106 | width: 100%;
107 | z-index: 1;
108 | margin-top: 26px; }
109 | #breadcrumbs #carat {
110 | height: 10px;
111 | margin: 0 5px; }
112 |
113 | .sidebar {
114 | background-color: #f9f9f9;
115 | border: 1px solid #e2e2e2;
116 | overflow-y: auto;
117 | overflow-x: hidden;
118 | position: fixed;
119 | top: 70px;
120 | bottom: 0;
121 | width: 230px;
122 | word-wrap: normal; }
123 |
124 | .nav-groups {
125 | list-style-type: none;
126 | background: #fff;
127 | padding-left: 0; }
128 |
129 | .nav-group-name {
130 | border-bottom: 1px solid #e2e2e2;
131 | font-size: 1.1em;
132 | font-weight: 100;
133 | padding: 15px 0 15px 20px; }
134 | .nav-group-name > a {
135 | color: #333; }
136 |
137 | .nav-group-tasks {
138 | margin-top: 5px; }
139 |
140 | .nav-group-task {
141 | font-size: 0.9em;
142 | list-style-type: none;
143 | white-space: nowrap; }
144 | .nav-group-task a {
145 | color: #888; }
146 |
147 | .main-content {
148 | background-color: #fff;
149 | border: 1px solid #e2e2e2;
150 | margin-left: 246px;
151 | position: absolute;
152 | overflow: hidden;
153 | padding-bottom: 20px;
154 | top: 70px;
155 | width: 734px; }
156 | .main-content p, .main-content a, .main-content code, .main-content em, .main-content ul, .main-content table, .main-content blockquote {
157 | margin-bottom: 1em; }
158 | .main-content p {
159 | line-height: 1.8em; }
160 | .main-content section .section:first-child {
161 | margin-top: 0;
162 | padding-top: 0; }
163 | .main-content section .task-group-section .task-group:first-of-type {
164 | padding-top: 10px; }
165 | .main-content section .task-group-section .task-group:first-of-type .section-name {
166 | padding-top: 15px; }
167 | .main-content section .heading:before {
168 | content: "";
169 | display: block;
170 | padding-top: 70px;
171 | margin: -70px 0 0; }
172 |
173 | .section {
174 | padding: 0 25px; }
175 |
176 | .highlight {
177 | background-color: #eee;
178 | padding: 10px 12px;
179 | border: 1px solid #e2e2e2;
180 | border-radius: 4px;
181 | overflow-x: auto; }
182 |
183 | .declaration .highlight {
184 | overflow-x: initial;
185 | padding: 0 40px 40px 0;
186 | margin-bottom: -25px;
187 | background-color: transparent;
188 | border: none; }
189 |
190 | .section-name {
191 | margin: 0;
192 | margin-left: 18px; }
193 |
194 | .task-group-section {
195 | padding-left: 6px;
196 | border-top: 1px solid #e2e2e2; }
197 |
198 | .task-group {
199 | padding-top: 0px; }
200 |
201 | .task-name-container a[name]:before {
202 | content: "";
203 | display: block;
204 | padding-top: 70px;
205 | margin: -70px 0 0; }
206 |
207 | .item {
208 | padding-top: 8px;
209 | width: 100%;
210 | list-style-type: none; }
211 | .item a[name]:before {
212 | content: "";
213 | display: block;
214 | padding-top: 70px;
215 | margin: -70px 0 0; }
216 | .item code {
217 | background-color: transparent;
218 | padding: 0; }
219 | .item .token, .item .direct-link {
220 | padding-left: 3px;
221 | margin-left: 15px;
222 | font-size: 11.9px; }
223 | .item .discouraged {
224 | text-decoration: line-through; }
225 | .item .declaration-note {
226 | font-size: .85em;
227 | color: gray;
228 | font-style: italic; }
229 |
230 | .pointer-container {
231 | border-bottom: 1px solid #e2e2e2;
232 | left: -23px;
233 | padding-bottom: 13px;
234 | position: relative;
235 | width: 110%; }
236 |
237 | .pointer {
238 | background: #f9f9f9;
239 | border-left: 1px solid #e2e2e2;
240 | border-top: 1px solid #e2e2e2;
241 | height: 12px;
242 | left: 21px;
243 | top: -7px;
244 | -webkit-transform: rotate(45deg);
245 | -moz-transform: rotate(45deg);
246 | -o-transform: rotate(45deg);
247 | transform: rotate(45deg);
248 | position: absolute;
249 | width: 12px; }
250 |
251 | .height-container {
252 | display: none;
253 | left: -25px;
254 | padding: 0 25px;
255 | position: relative;
256 | width: 100%;
257 | overflow: hidden; }
258 | .height-container .section {
259 | background: #f9f9f9;
260 | border-bottom: 1px solid #e2e2e2;
261 | left: -25px;
262 | position: relative;
263 | width: 100%;
264 | padding-top: 10px;
265 | padding-bottom: 5px; }
266 |
267 | .aside, .language {
268 | padding: 6px 12px;
269 | margin: 12px 0;
270 | border-left: 5px solid #dddddd;
271 | overflow-y: hidden; }
272 | .aside .aside-title, .language .aside-title {
273 | font-size: 9px;
274 | letter-spacing: 2px;
275 | text-transform: uppercase;
276 | padding-bottom: 0;
277 | margin: 0;
278 | color: #aaa;
279 | -webkit-user-select: none; }
280 | .aside p:last-child, .language p:last-child {
281 | margin-bottom: 0; }
282 |
283 | .language {
284 | border-left: 5px solid #cde9f4; }
285 | .language .aside-title {
286 | color: #4b8afb; }
287 |
288 | .aside-warning, .aside-deprecated, .aside-unavailable {
289 | border-left: 5px solid #ff6666; }
290 | .aside-warning .aside-title, .aside-deprecated .aside-title, .aside-unavailable .aside-title {
291 | color: #ff0000; }
292 |
293 | .graybox {
294 | border-collapse: collapse;
295 | width: 100%; }
296 | .graybox p {
297 | margin: 0;
298 | word-break: break-word;
299 | min-width: 50px; }
300 | .graybox td {
301 | border: 1px solid #e2e2e2;
302 | padding: 5px 25px 5px 10px;
303 | vertical-align: middle; }
304 | .graybox tr td:first-of-type {
305 | text-align: right;
306 | padding: 7px;
307 | vertical-align: top;
308 | word-break: normal;
309 | width: 40px; }
310 |
311 | .slightly-smaller {
312 | font-size: 0.9em; }
313 |
314 | #footer {
315 | position: relative;
316 | top: 10px;
317 | bottom: 0px;
318 | margin-left: 25px; }
319 | #footer p {
320 | margin: 0;
321 | color: #aaa;
322 | font-size: 0.8em; }
323 |
324 | html.dash header, html.dash #breadcrumbs, html.dash .sidebar {
325 | display: none; }
326 | html.dash .main-content {
327 | width: 980px;
328 | margin-left: 0;
329 | border: none;
330 | width: 100%;
331 | top: 0;
332 | padding-bottom: 0; }
333 | html.dash .height-container {
334 | display: block; }
335 | html.dash .item .token {
336 | margin-left: 0; }
337 | html.dash .content-wrapper {
338 | width: auto; }
339 | html.dash #footer {
340 | position: static; }
341 |
--------------------------------------------------------------------------------
/docs/docsets/froop.docset/Contents/Resources/Documents/img/carat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lookback/froop-swift/bab0e82ad0315950ebc2e01c88c1844e9d6720e9/docs/docsets/froop.docset/Contents/Resources/Documents/img/carat.png
--------------------------------------------------------------------------------
/docs/docsets/froop.docset/Contents/Resources/Documents/img/dash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lookback/froop-swift/bab0e82ad0315950ebc2e01c88c1844e9d6720e9/docs/docsets/froop.docset/Contents/Resources/Documents/img/dash.png
--------------------------------------------------------------------------------
/docs/docsets/froop.docset/Contents/Resources/Documents/img/gh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lookback/froop-swift/bab0e82ad0315950ebc2e01c88c1844e9d6720e9/docs/docsets/froop.docset/Contents/Resources/Documents/img/gh.png
--------------------------------------------------------------------------------
/docs/docsets/froop.docset/Contents/Resources/Documents/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | froop Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
20 |
21 |
22 | froop Reference
23 |
24 | froop Reference
25 |
26 |
27 |
28 |
81 |
82 |
83 |
84 |
85 | froop
86 | Authors
87 |
88 | Lookback
89 |
90 |
91 |
92 |
96 |
97 |
98 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/docs/docsets/froop.docset/Contents/Resources/Documents/js/jazzy.js:
--------------------------------------------------------------------------------
1 | window.jazzy = {'docset': false}
2 | if (typeof window.dash != 'undefined') {
3 | document.documentElement.className += ' dash'
4 | window.jazzy.docset = true
5 | }
6 | if (navigator.userAgent.match(/xcode/i)) {
7 | document.documentElement.className += ' xcode'
8 | window.jazzy.docset = true
9 | }
10 |
11 | // On doc load, toggle the URL hash discussion if present
12 | $(document).ready(function() {
13 | if (!window.jazzy.docset) {
14 | var linkToHash = $('a[href="' + window.location.hash +'"]');
15 | linkToHash.trigger("click");
16 | }
17 | });
18 |
19 | // On token click, toggle its discussion and animate token.marginLeft
20 | $(".token").click(function(event) {
21 | if (window.jazzy.docset) {
22 | return;
23 | }
24 | var link = $(this);
25 | var animationDuration = 300;
26 | var tokenOffset = "15px";
27 | var original = link.css('marginLeft') == tokenOffset;
28 | link.animate({'margin-left':original ? "0px" : tokenOffset}, animationDuration);
29 | $content = link.parent().parent().next();
30 | $content.slideToggle(animationDuration);
31 |
32 | // Keeps the document from jumping to the hash.
33 | var href = $(this).attr('href');
34 | if (history.pushState) {
35 | history.pushState({}, '', href);
36 | } else {
37 | location.hash = href;
38 | }
39 | event.preventDefault();
40 | });
41 |
42 | // Dumb down quotes within code blocks that delimit strings instead of quotations
43 | // https://github.com/realm/jazzy/issues/714
44 | $("code q").replaceWith(function () {
45 | return ["\"", $(this).contents(), "\""];
46 | });
47 |
--------------------------------------------------------------------------------
/docs/docsets/froop.docset/Contents/Resources/Documents/search.json:
--------------------------------------------------------------------------------
1 | {"Functions.html#/s:5froop7flatten6nestedAA6StreamCyxGAEyAFG_tlF":{"name":"flatten(nested:)","abstract":"Flatten a stream of streams, sequentially. This means that any new stream"},"Functions.html#/s:5froop19flattenConcurrently6nestedAA6StreamCyxGAEyAFG_tlF":{"name":"flattenConcurrently(nested:)","abstract":"
Flatten a stream of streams, concurrently. This means that any new stream"},"Functions.html#/s:5froop5mergeyAA6StreamCyxGAEd_tlF":{"name":"merge(_:)","abstract":"
Merge a bunch of streams emitting the same T to one.
"},"Functions.html#/s:5froop7combineyAA6StreamCyx_q_tGADyxG_ADyq_Gtr0_lF":{"name":"combine(_:_:)","abstract":"Combine a number of streams and emit values when any of them emit a value.
"},"Functions.html#/s:5froop7combineyAA6StreamCyx_q_q0_tGADyxG_ADyq_GADyq0_Gtr1_lF":{"name":"combine(_:_:_:)","abstract":"Combine a number of streams and emit values when any of them emit a value.
"},"Functions.html#/s:5froop7combineyAA6StreamCyx_q_q0_q1_tGADyxG_ADyq_GADyq0_GADyq1_Gtr2_lF":{"name":"combine(_:_:_:_:)","abstract":"Combine a number of streams and emit values when any of them emit a value.
"},"Functions.html#/s:5froop7combineyAA6StreamCyx_q_q0_q1_q2_tGADyxG_ADyq_GADyq0_GADyq1_GADyq2_Gtr3_lF":{"name":"combine(_:_:_:_:_:)","abstract":"Combine a number of streams and emit values when any of them emit a value.
"},"Classes/Imitator.html#/s:5froop8ImitatorC6streamAA6StreamCyxGyF":{"name":"stream()","abstract":"Get a stream from this imitator. Can be used multiple times and each instance","parent_name":"Imitator"},"Classes/Imitator.html#/s:5froop8ImitatorC7imitate5otheryAA6StreamCyxG_tF":{"name":"imitate(other:)","abstract":"
Start imitating another stream. This can be called exactly once.","parent_name":"Imitator"},"Classes/Subscription.html#/s:5froop12SubscriptionC11unsubscribeyyF":{"name":"unsubscribe()","abstract":"
Unsubscribe from further updates.
","parent_name":"Subscription"},"Classes/Collector.html#/s:5froop9CollectorC4waitSayxGyF":{"name":"wait()","abstract":"Stall the thread and wait for the stream this collector works off to end.
","parent_name":"Collector"},"Classes/Collector.html#/s:5froop9CollectorC4takeSayxGyF":{"name":"take()","abstract":"Take whatever values are in the collector without waiting for","parent_name":"Collector"},"Classes/Sink.html#/s:5froop4SinkCACyxGycfc":{"name":"init()","abstract":"
Create a new sink.
","parent_name":"Sink"},"Classes/Sink.html#/s:5froop4SinkC6streamAA6StreamCyxGyF":{"name":"stream()","abstract":"Get a stream from this sink. Can be used multiple times and each instance","parent_name":"Sink"},"Classes/Sink.html#/s:5froop4SinkC6updateyyxF":{"name":"update(_:)","abstract":"
Update a value into the sink and all connected streams.
","parent_name":"Sink"},"Classes/Sink.html#/s:5froop4SinkC3endyyF":{"name":"end()","abstract":"End this sink. No more values can be sent after this.
","parent_name":"Sink"},"Classes/Stream.html#/s:5froop6StreamC9subscribeyAA12SubscriptionCyxGyxSgcF":{"name":"subscribe(_:)","abstract":"Subscribe to values from this stream. Nil indicates the end of","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC7collectAA9CollectorCyxGyF":{"name":"collect()","abstract":"
Collect values of this stream into an array of values.
","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC8dedupeByyACyxGqd__xcSQRd__lF":{"name":"dedupeBy(_:)","abstract":"Dedupe the stream by extracting some equatable value from it.","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC4drop6amountACyxGSu_tF":{"name":"drop(amount:)","abstract":"
Drop a fixed number of initial values, then start emitting.
","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC9dropWhileyACyxGSbxcF":{"name":"dropWhile(_:)","abstract":"Drop values while some condition holds true, then start emitting.","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC7endWhen5otherACyxGACyqd__G_tlF":{"name":"endWhen(other:)","abstract":"
Make a stream that ends when some other stream ends.
","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC6filteryACyxGSbxcF":{"name":"filter(_:)","abstract":"Filter the stream using some sort of test.
","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC4foldyAA06MemoryB0Cyqd__Gqd___qd__qd___xtctlF":{"name":"fold(_:_:)","abstract":"Fold the stream by combining values from the past with the new value.","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC4lastACyxGyF":{"name":"last()","abstract":"
Makes a stream that only emits the last value.
","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC3mapyACyqd__Gqd__xclF":{"name":"map(_:)","abstract":"Transform values of type T to type U.
","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC5mapTo5valueACyqd__Gqd___tlF":{"name":"mapTo(value:)","abstract":"Transform any incoming value to one fixed value.
","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC8rememberAA06MemoryB0CyxGyF":{"name":"remember()","abstract":"Make a stream that remembers the last value. Any new (or combinator) will get the","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC13sampleCombineyACyx_qd__tGACyqd__GlF":{"name":"sampleCombine(_:)","abstract":"
For every value of this stream, take a sample of the last value of some other","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC9startWith5valueAA06MemoryB0CyxGx_tF":{"name":"startWith(value:)","abstract":"
Prepend a value to a stream. Or in other words, give a start value to a stream.
","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC4take6amountACyxGSu_tF":{"name":"take(amount:)","abstract":"Take a fixed amount of elements, then end.
","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC9takeWhileyACyxGSbxcF":{"name":"takeWhile(_:)","abstract":"Take values from the stream while some condition hold true, then end the stream.
","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC4waityyF":{"name":"wait()","abstract":"Stall the thread until the stream to ends.
","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamCAASQRzlE6dedupeACyxGyF":{"name":"dedupe()","abstract":"Dedupe the stream by the value in the stream itself
","parent_name":"Stream"},"Classes/Stream.html":{"name":"Stream","abstract":"Stream of vaules over time. Typically created by a Sink.
"},"Classes.html#/s:5froop12MemoryStreamC":{"name":"MemoryStream","abstract":"Specialization of Stream that has memory . Memory means that any"},"Classes/Sink.html":{"name":"Sink","abstract":"
The originator of a stream of values.
"},"Classes/Collector.html":{"name":"Collector","abstract":"Helper to collect values from a stream. Mainly useful for tests.
"},"Classes/Subscription.html":{"name":"Subscription","abstract":"Subscriptions are receipts to the Stream.subscribe()
operation. They"},"Classes/Imitator.html":{"name":"Imitator","abstract":"
Imitators are used to create cyclic streams. The imitator is an originator"},"Classes.html":{"name":"Classes","abstract":"
The following classes are available globally.
"},"Functions.html":{"name":"Functions","abstract":"The following functions are available globally.
"}}
--------------------------------------------------------------------------------
/docs/docsets/froop.docset/Contents/Resources/docSet.dsidx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lookback/froop-swift/bab0e82ad0315950ebc2e01c88c1844e9d6720e9/docs/docsets/froop.docset/Contents/Resources/docSet.dsidx
--------------------------------------------------------------------------------
/docs/docsets/froop.tgz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lookback/froop-swift/bab0e82ad0315950ebc2e01c88c1844e9d6720e9/docs/docsets/froop.tgz
--------------------------------------------------------------------------------
/docs/img/carat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lookback/froop-swift/bab0e82ad0315950ebc2e01c88c1844e9d6720e9/docs/img/carat.png
--------------------------------------------------------------------------------
/docs/img/dash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lookback/froop-swift/bab0e82ad0315950ebc2e01c88c1844e9d6720e9/docs/img/dash.png
--------------------------------------------------------------------------------
/docs/img/gh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lookback/froop-swift/bab0e82ad0315950ebc2e01c88c1844e9d6720e9/docs/img/gh.png
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | froop Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
20 |
21 |
22 | froop Reference
23 |
24 | froop Reference
25 |
26 |
27 |
28 |
81 |
82 |
83 |
84 |
85 | froop
86 | Authors
87 |
88 | Lookback
89 |
90 |
91 |
92 |
96 |
97 |
98 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/docs/js/jazzy.js:
--------------------------------------------------------------------------------
1 | window.jazzy = {'docset': false}
2 | if (typeof window.dash != 'undefined') {
3 | document.documentElement.className += ' dash'
4 | window.jazzy.docset = true
5 | }
6 | if (navigator.userAgent.match(/xcode/i)) {
7 | document.documentElement.className += ' xcode'
8 | window.jazzy.docset = true
9 | }
10 |
11 | // On doc load, toggle the URL hash discussion if present
12 | $(document).ready(function() {
13 | if (!window.jazzy.docset) {
14 | var linkToHash = $('a[href="' + window.location.hash +'"]');
15 | linkToHash.trigger("click");
16 | }
17 | });
18 |
19 | // On token click, toggle its discussion and animate token.marginLeft
20 | $(".token").click(function(event) {
21 | if (window.jazzy.docset) {
22 | return;
23 | }
24 | var link = $(this);
25 | var animationDuration = 300;
26 | var tokenOffset = "15px";
27 | var original = link.css('marginLeft') == tokenOffset;
28 | link.animate({'margin-left':original ? "0px" : tokenOffset}, animationDuration);
29 | $content = link.parent().parent().next();
30 | $content.slideToggle(animationDuration);
31 |
32 | // Keeps the document from jumping to the hash.
33 | var href = $(this).attr('href');
34 | if (history.pushState) {
35 | history.pushState({}, '', href);
36 | } else {
37 | location.hash = href;
38 | }
39 | event.preventDefault();
40 | });
41 |
42 | // Dumb down quotes within code blocks that delimit strings instead of quotations
43 | // https://github.com/realm/jazzy/issues/714
44 | $("code q").replaceWith(function () {
45 | return ["\"", $(this).contents(), "\""];
46 | });
47 |
--------------------------------------------------------------------------------
/docs/search.json:
--------------------------------------------------------------------------------
1 | {"Functions.html#/s:5froop7flatten6nestedAA6StreamCyxGAEyAFG_tlF":{"name":"flatten(nested:)","abstract":"Flatten a stream of streams, sequentially. This means that any new stream"},"Functions.html#/s:5froop19flattenConcurrently6nestedAA6StreamCyxGAEyAFG_tlF":{"name":"flattenConcurrently(nested:)","abstract":"
Flatten a stream of streams, concurrently. This means that any new stream"},"Functions.html#/s:5froop5mergeyAA6StreamCyxGAEd_tlF":{"name":"merge(_:)","abstract":"
Merge a bunch of streams emitting the same T to one.
"},"Functions.html#/s:5froop7combineyAA6StreamCyx_q_tGADyxG_ADyq_Gtr0_lF":{"name":"combine(_:_:)","abstract":"Combine a number of streams and emit values when any of them emit a value.
"},"Functions.html#/s:5froop7combineyAA6StreamCyx_q_q0_tGADyxG_ADyq_GADyq0_Gtr1_lF":{"name":"combine(_:_:_:)","abstract":"Combine a number of streams and emit values when any of them emit a value.
"},"Functions.html#/s:5froop7combineyAA6StreamCyx_q_q0_q1_tGADyxG_ADyq_GADyq0_GADyq1_Gtr2_lF":{"name":"combine(_:_:_:_:)","abstract":"Combine a number of streams and emit values when any of them emit a value.
"},"Functions.html#/s:5froop7combineyAA6StreamCyx_q_q0_q1_q2_tGADyxG_ADyq_GADyq0_GADyq1_GADyq2_Gtr3_lF":{"name":"combine(_:_:_:_:_:)","abstract":"Combine a number of streams and emit values when any of them emit a value.
"},"Classes/Imitator.html#/s:5froop8ImitatorC6streamAA6StreamCyxGyF":{"name":"stream()","abstract":"Get a stream from this imitator. Can be used multiple times and each instance","parent_name":"Imitator"},"Classes/Imitator.html#/s:5froop8ImitatorC7imitate5otheryAA6StreamCyxG_tF":{"name":"imitate(other:)","abstract":"
Start imitating another stream. This can be called exactly once.","parent_name":"Imitator"},"Classes/Subscription.html#/s:5froop12SubscriptionC11unsubscribeyyF":{"name":"unsubscribe()","abstract":"
Unsubscribe from further updates.
","parent_name":"Subscription"},"Classes/Collector.html#/s:5froop9CollectorC4waitSayxGyF":{"name":"wait()","abstract":"Stall the thread and wait for the stream this collector works off to end.
","parent_name":"Collector"},"Classes/Collector.html#/s:5froop9CollectorC4takeSayxGyF":{"name":"take()","abstract":"Take whatever values are in the collector without waiting for","parent_name":"Collector"},"Classes/Sink.html#/s:5froop4SinkCACyxGycfc":{"name":"init()","abstract":"
Create a new sink.
","parent_name":"Sink"},"Classes/Sink.html#/s:5froop4SinkC6streamAA6StreamCyxGyF":{"name":"stream()","abstract":"Get a stream from this sink. Can be used multiple times and each instance","parent_name":"Sink"},"Classes/Sink.html#/s:5froop4SinkC6updateyyxF":{"name":"update(_:)","abstract":"
Update a value into the sink and all connected streams.
","parent_name":"Sink"},"Classes/Sink.html#/s:5froop4SinkC3endyyF":{"name":"end()","abstract":"End this sink. No more values can be sent after this.
","parent_name":"Sink"},"Classes/Stream.html#/s:5froop6StreamC9subscribeyAA12SubscriptionCyxGyxSgcF":{"name":"subscribe(_:)","abstract":"Subscribe to values from this stream. Nil indicates the end of","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC7collectAA9CollectorCyxGyF":{"name":"collect()","abstract":"
Collect values of this stream into an array of values.
","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC8dedupeByyACyxGqd__xcSQRd__lF":{"name":"dedupeBy(_:)","abstract":"Dedupe the stream by extracting some equatable value from it.","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC4drop6amountACyxGSu_tF":{"name":"drop(amount:)","abstract":"
Drop a fixed number of initial values, then start emitting.
","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC9dropWhileyACyxGSbxcF":{"name":"dropWhile(_:)","abstract":"Drop values while some condition holds true, then start emitting.","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC7endWhen5otherACyxGACyqd__G_tlF":{"name":"endWhen(other:)","abstract":"
Make a stream that ends when some other stream ends.
","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC6filteryACyxGSbxcF":{"name":"filter(_:)","abstract":"Filter the stream using some sort of test.
","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC4foldyAA06MemoryB0Cyqd__Gqd___qd__qd___xtctlF":{"name":"fold(_:_:)","abstract":"Fold the stream by combining values from the past with the new value.","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC4lastACyxGyF":{"name":"last()","abstract":"
Makes a stream that only emits the last value.
","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC3mapyACyqd__Gqd__xclF":{"name":"map(_:)","abstract":"Transform values of type T to type U.
","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC5mapTo5valueACyqd__Gqd___tlF":{"name":"mapTo(value:)","abstract":"Transform any incoming value to one fixed value.
","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC8rememberAA06MemoryB0CyxGyF":{"name":"remember()","abstract":"Make a stream that remembers the last value. Any new (or combinator) will get the","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC13sampleCombineyACyx_qd__tGACyqd__GlF":{"name":"sampleCombine(_:)","abstract":"
For every value of this stream, take a sample of the last value of some other","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC9startWith5valueAA06MemoryB0CyxGx_tF":{"name":"startWith(value:)","abstract":"
Prepend a value to a stream. Or in other words, give a start value to a stream.
","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC4take6amountACyxGSu_tF":{"name":"take(amount:)","abstract":"Take a fixed amount of elements, then end.
","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC9takeWhileyACyxGSbxcF":{"name":"takeWhile(_:)","abstract":"Take values from the stream while some condition hold true, then end the stream.
","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamC4waityyF":{"name":"wait()","abstract":"Stall the thread until the stream to ends.
","parent_name":"Stream"},"Classes/Stream.html#/s:5froop6StreamCAASQRzlE6dedupeACyxGyF":{"name":"dedupe()","abstract":"Dedupe the stream by the value in the stream itself
","parent_name":"Stream"},"Classes/Stream.html":{"name":"Stream","abstract":"Stream of vaules over time. Typically created by a Sink.
"},"Classes.html#/s:5froop12MemoryStreamC":{"name":"MemoryStream","abstract":"Specialization of Stream that has memory . Memory means that any"},"Classes/Sink.html":{"name":"Sink","abstract":"
The originator of a stream of values.
"},"Classes/Collector.html":{"name":"Collector","abstract":"Helper to collect values from a stream. Mainly useful for tests.
"},"Classes/Subscription.html":{"name":"Subscription","abstract":"Subscriptions are receipts to the Stream.subscribe()
operation. They"},"Classes/Imitator.html":{"name":"Imitator","abstract":"
Imitators are used to create cyclic streams. The imitator is an originator"},"Classes.html":{"name":"Classes","abstract":"
The following classes are available globally.
"},"Functions.html":{"name":"Functions","abstract":"The following functions are available globally.
"}}
--------------------------------------------------------------------------------
/docs/undocumented.json:
--------------------------------------------------------------------------------
1 | {
2 | "warnings": [
3 |
4 | ],
5 | "source_directory": "/Users/martin/Desktop/froop"
6 | }
--------------------------------------------------------------------------------
/froop.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 50;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 5B891BFF2222EC47002F31C6 /* froop.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B891BF52222EC46002F31C6 /* froop.framework */; };
11 | 5B891C042222EC47002F31C6 /* froopTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B891C032222EC47002F31C6 /* froopTests.swift */; };
12 | 5B891C062222EC47002F31C6 /* froop.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B891BF82222EC46002F31C6 /* froop.h */; settings = {ATTRIBUTES = (Public, ); }; };
13 | 5B891C102222EC5D002F31C6 /* froop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B891C0F2222EC5D002F31C6 /* froop.swift */; };
14 | 5B891C122222ECC1002F31C6 /* Threadly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B891C112222ECC1002F31C6 /* Threadly.swift */; };
15 | /* End PBXBuildFile section */
16 |
17 | /* Begin PBXContainerItemProxy section */
18 | 5B891C002222EC47002F31C6 /* PBXContainerItemProxy */ = {
19 | isa = PBXContainerItemProxy;
20 | containerPortal = 5B891BEC2222EC46002F31C6 /* Project object */;
21 | proxyType = 1;
22 | remoteGlobalIDString = 5B891BF42222EC46002F31C6;
23 | remoteInfo = froop;
24 | };
25 | /* End PBXContainerItemProxy section */
26 |
27 | /* Begin PBXFileReference section */
28 | 5B891BF52222EC46002F31C6 /* froop.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = froop.framework; sourceTree = BUILT_PRODUCTS_DIR; };
29 | 5B891BF82222EC46002F31C6 /* froop.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = froop.h; sourceTree = ""; };
30 | 5B891BF92222EC46002F31C6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
31 | 5B891BFE2222EC47002F31C6 /* froopTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = froopTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
32 | 5B891C032222EC47002F31C6 /* froopTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = froopTests.swift; sourceTree = ""; };
33 | 5B891C052222EC47002F31C6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
34 | 5B891C0F2222EC5D002F31C6 /* froop.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = froop.swift; sourceTree = ""; };
35 | 5B891C112222ECC1002F31C6 /* Threadly.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Threadly.swift; sourceTree = ""; };
36 | /* End PBXFileReference section */
37 |
38 | /* Begin PBXFrameworksBuildPhase section */
39 | 5B891BF22222EC46002F31C6 /* Frameworks */ = {
40 | isa = PBXFrameworksBuildPhase;
41 | buildActionMask = 2147483647;
42 | files = (
43 | );
44 | runOnlyForDeploymentPostprocessing = 0;
45 | };
46 | 5B891BFB2222EC47002F31C6 /* Frameworks */ = {
47 | isa = PBXFrameworksBuildPhase;
48 | buildActionMask = 2147483647;
49 | files = (
50 | 5B891BFF2222EC47002F31C6 /* froop.framework in Frameworks */,
51 | );
52 | runOnlyForDeploymentPostprocessing = 0;
53 | };
54 | /* End PBXFrameworksBuildPhase section */
55 |
56 | /* Begin PBXGroup section */
57 | 5B891BEB2222EC46002F31C6 = {
58 | isa = PBXGroup;
59 | children = (
60 | 5B891BF72222EC46002F31C6 /* froop */,
61 | 5B891C022222EC47002F31C6 /* froopTests */,
62 | 5B891BF62222EC46002F31C6 /* Products */,
63 | );
64 | sourceTree = "";
65 | };
66 | 5B891BF62222EC46002F31C6 /* Products */ = {
67 | isa = PBXGroup;
68 | children = (
69 | 5B891BF52222EC46002F31C6 /* froop.framework */,
70 | 5B891BFE2222EC47002F31C6 /* froopTests.xctest */,
71 | );
72 | name = Products;
73 | sourceTree = "";
74 | };
75 | 5B891BF72222EC46002F31C6 /* froop */ = {
76 | isa = PBXGroup;
77 | children = (
78 | 5B891BF82222EC46002F31C6 /* froop.h */,
79 | 5B891C0F2222EC5D002F31C6 /* froop.swift */,
80 | 5B891BF92222EC46002F31C6 /* Info.plist */,
81 | 5B891C112222ECC1002F31C6 /* Threadly.swift */,
82 | );
83 | path = froop;
84 | sourceTree = "";
85 | };
86 | 5B891C022222EC47002F31C6 /* froopTests */ = {
87 | isa = PBXGroup;
88 | children = (
89 | 5B891C032222EC47002F31C6 /* froopTests.swift */,
90 | 5B891C052222EC47002F31C6 /* Info.plist */,
91 | );
92 | path = froopTests;
93 | sourceTree = "";
94 | };
95 | /* End PBXGroup section */
96 |
97 | /* Begin PBXHeadersBuildPhase section */
98 | 5B891BF02222EC46002F31C6 /* Headers */ = {
99 | isa = PBXHeadersBuildPhase;
100 | buildActionMask = 2147483647;
101 | files = (
102 | 5B891C062222EC47002F31C6 /* froop.h in Headers */,
103 | );
104 | runOnlyForDeploymentPostprocessing = 0;
105 | };
106 | /* End PBXHeadersBuildPhase section */
107 |
108 | /* Begin PBXNativeTarget section */
109 | 5B891BF42222EC46002F31C6 /* froop */ = {
110 | isa = PBXNativeTarget;
111 | buildConfigurationList = 5B891C092222EC47002F31C6 /* Build configuration list for PBXNativeTarget "froop" */;
112 | buildPhases = (
113 | 5B891BF02222EC46002F31C6 /* Headers */,
114 | 5B891BF12222EC46002F31C6 /* Sources */,
115 | 5B891BF22222EC46002F31C6 /* Frameworks */,
116 | 5B891BF32222EC46002F31C6 /* Resources */,
117 | );
118 | buildRules = (
119 | );
120 | dependencies = (
121 | );
122 | name = froop;
123 | productName = froop;
124 | productReference = 5B891BF52222EC46002F31C6 /* froop.framework */;
125 | productType = "com.apple.product-type.framework";
126 | };
127 | 5B891BFD2222EC47002F31C6 /* froopTests */ = {
128 | isa = PBXNativeTarget;
129 | buildConfigurationList = 5B891C0C2222EC47002F31C6 /* Build configuration list for PBXNativeTarget "froopTests" */;
130 | buildPhases = (
131 | 5B891BFA2222EC47002F31C6 /* Sources */,
132 | 5B891BFB2222EC47002F31C6 /* Frameworks */,
133 | 5B891BFC2222EC47002F31C6 /* Resources */,
134 | );
135 | buildRules = (
136 | );
137 | dependencies = (
138 | 5B891C012222EC47002F31C6 /* PBXTargetDependency */,
139 | );
140 | name = froopTests;
141 | productName = froopTests;
142 | productReference = 5B891BFE2222EC47002F31C6 /* froopTests.xctest */;
143 | productType = "com.apple.product-type.bundle.unit-test";
144 | };
145 | /* End PBXNativeTarget section */
146 |
147 | /* Begin PBXProject section */
148 | 5B891BEC2222EC46002F31C6 /* Project object */ = {
149 | isa = PBXProject;
150 | attributes = {
151 | LastSwiftUpdateCheck = 1010;
152 | LastUpgradeCheck = 1250;
153 | ORGANIZATIONNAME = "Lookback Ltd";
154 | TargetAttributes = {
155 | 5B891BF42222EC46002F31C6 = {
156 | CreatedOnToolsVersion = 10.1;
157 | LastSwiftMigration = 1020;
158 | };
159 | 5B891BFD2222EC47002F31C6 = {
160 | CreatedOnToolsVersion = 10.1;
161 | LastSwiftMigration = 1020;
162 | };
163 | };
164 | };
165 | buildConfigurationList = 5B891BEF2222EC46002F31C6 /* Build configuration list for PBXProject "froop" */;
166 | compatibilityVersion = "Xcode 9.3";
167 | developmentRegion = en;
168 | hasScannedForEncodings = 0;
169 | knownRegions = (
170 | en,
171 | Base,
172 | );
173 | mainGroup = 5B891BEB2222EC46002F31C6;
174 | productRefGroup = 5B891BF62222EC46002F31C6 /* Products */;
175 | projectDirPath = "";
176 | projectRoot = "";
177 | targets = (
178 | 5B891BF42222EC46002F31C6 /* froop */,
179 | 5B891BFD2222EC47002F31C6 /* froopTests */,
180 | );
181 | };
182 | /* End PBXProject section */
183 |
184 | /* Begin PBXResourcesBuildPhase section */
185 | 5B891BF32222EC46002F31C6 /* Resources */ = {
186 | isa = PBXResourcesBuildPhase;
187 | buildActionMask = 2147483647;
188 | files = (
189 | );
190 | runOnlyForDeploymentPostprocessing = 0;
191 | };
192 | 5B891BFC2222EC47002F31C6 /* Resources */ = {
193 | isa = PBXResourcesBuildPhase;
194 | buildActionMask = 2147483647;
195 | files = (
196 | );
197 | runOnlyForDeploymentPostprocessing = 0;
198 | };
199 | /* End PBXResourcesBuildPhase section */
200 |
201 | /* Begin PBXSourcesBuildPhase section */
202 | 5B891BF12222EC46002F31C6 /* Sources */ = {
203 | isa = PBXSourcesBuildPhase;
204 | buildActionMask = 2147483647;
205 | files = (
206 | 5B891C122222ECC1002F31C6 /* Threadly.swift in Sources */,
207 | 5B891C102222EC5D002F31C6 /* froop.swift in Sources */,
208 | );
209 | runOnlyForDeploymentPostprocessing = 0;
210 | };
211 | 5B891BFA2222EC47002F31C6 /* Sources */ = {
212 | isa = PBXSourcesBuildPhase;
213 | buildActionMask = 2147483647;
214 | files = (
215 | 5B891C042222EC47002F31C6 /* froopTests.swift in Sources */,
216 | );
217 | runOnlyForDeploymentPostprocessing = 0;
218 | };
219 | /* End PBXSourcesBuildPhase section */
220 |
221 | /* Begin PBXTargetDependency section */
222 | 5B891C012222EC47002F31C6 /* PBXTargetDependency */ = {
223 | isa = PBXTargetDependency;
224 | target = 5B891BF42222EC46002F31C6 /* froop */;
225 | targetProxy = 5B891C002222EC47002F31C6 /* PBXContainerItemProxy */;
226 | };
227 | /* End PBXTargetDependency section */
228 |
229 | /* Begin XCBuildConfiguration section */
230 | 5B891C072222EC47002F31C6 /* Debug */ = {
231 | isa = XCBuildConfiguration;
232 | buildSettings = {
233 | ALWAYS_SEARCH_USER_PATHS = NO;
234 | CLANG_ANALYZER_NONNULL = YES;
235 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
236 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
237 | CLANG_CXX_LIBRARY = "libc++";
238 | CLANG_ENABLE_MODULES = YES;
239 | CLANG_ENABLE_OBJC_ARC = YES;
240 | CLANG_ENABLE_OBJC_WEAK = YES;
241 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
242 | CLANG_WARN_BOOL_CONVERSION = YES;
243 | CLANG_WARN_COMMA = YES;
244 | CLANG_WARN_CONSTANT_CONVERSION = YES;
245 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
246 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
247 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
248 | CLANG_WARN_EMPTY_BODY = YES;
249 | CLANG_WARN_ENUM_CONVERSION = YES;
250 | CLANG_WARN_INFINITE_RECURSION = YES;
251 | CLANG_WARN_INT_CONVERSION = YES;
252 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
253 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
254 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
255 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
256 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
257 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
258 | CLANG_WARN_STRICT_PROTOTYPES = YES;
259 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
260 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
261 | CLANG_WARN_UNREACHABLE_CODE = YES;
262 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
263 | CODE_SIGN_IDENTITY = "iPhone Developer";
264 | COPY_PHASE_STRIP = NO;
265 | CURRENT_PROJECT_VERSION = 1;
266 | DEBUG_INFORMATION_FORMAT = dwarf;
267 | ENABLE_STRICT_OBJC_MSGSEND = YES;
268 | ENABLE_TESTABILITY = YES;
269 | GCC_C_LANGUAGE_STANDARD = gnu11;
270 | GCC_DYNAMIC_NO_PIC = NO;
271 | GCC_NO_COMMON_BLOCKS = YES;
272 | GCC_OPTIMIZATION_LEVEL = 0;
273 | GCC_PREPROCESSOR_DEFINITIONS = (
274 | "DEBUG=1",
275 | "$(inherited)",
276 | );
277 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
278 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
279 | GCC_WARN_UNDECLARED_SELECTOR = YES;
280 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
281 | GCC_WARN_UNUSED_FUNCTION = YES;
282 | GCC_WARN_UNUSED_VARIABLE = YES;
283 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
284 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
285 | MTL_FAST_MATH = YES;
286 | ONLY_ACTIVE_ARCH = YES;
287 | SDKROOT = iphoneos;
288 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
289 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
290 | VERSIONING_SYSTEM = "apple-generic";
291 | VERSION_INFO_PREFIX = "";
292 | };
293 | name = Debug;
294 | };
295 | 5B891C082222EC47002F31C6 /* Release */ = {
296 | isa = XCBuildConfiguration;
297 | buildSettings = {
298 | ALWAYS_SEARCH_USER_PATHS = NO;
299 | CLANG_ANALYZER_NONNULL = YES;
300 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
301 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
302 | CLANG_CXX_LIBRARY = "libc++";
303 | CLANG_ENABLE_MODULES = YES;
304 | CLANG_ENABLE_OBJC_ARC = YES;
305 | CLANG_ENABLE_OBJC_WEAK = YES;
306 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
307 | CLANG_WARN_BOOL_CONVERSION = YES;
308 | CLANG_WARN_COMMA = YES;
309 | CLANG_WARN_CONSTANT_CONVERSION = YES;
310 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
311 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
312 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
313 | CLANG_WARN_EMPTY_BODY = YES;
314 | CLANG_WARN_ENUM_CONVERSION = YES;
315 | CLANG_WARN_INFINITE_RECURSION = YES;
316 | CLANG_WARN_INT_CONVERSION = YES;
317 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
318 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
319 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
320 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
321 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
322 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
323 | CLANG_WARN_STRICT_PROTOTYPES = YES;
324 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
325 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
326 | CLANG_WARN_UNREACHABLE_CODE = YES;
327 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
328 | CODE_SIGN_IDENTITY = "iPhone Developer";
329 | COPY_PHASE_STRIP = NO;
330 | CURRENT_PROJECT_VERSION = 1;
331 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
332 | ENABLE_NS_ASSERTIONS = NO;
333 | ENABLE_STRICT_OBJC_MSGSEND = YES;
334 | GCC_C_LANGUAGE_STANDARD = gnu11;
335 | GCC_NO_COMMON_BLOCKS = YES;
336 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
337 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
338 | GCC_WARN_UNDECLARED_SELECTOR = YES;
339 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
340 | GCC_WARN_UNUSED_FUNCTION = YES;
341 | GCC_WARN_UNUSED_VARIABLE = YES;
342 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
343 | MTL_ENABLE_DEBUG_INFO = NO;
344 | MTL_FAST_MATH = YES;
345 | SDKROOT = iphoneos;
346 | SWIFT_COMPILATION_MODE = wholemodule;
347 | SWIFT_OPTIMIZATION_LEVEL = "-O";
348 | VALIDATE_PRODUCT = YES;
349 | VERSIONING_SYSTEM = "apple-generic";
350 | VERSION_INFO_PREFIX = "";
351 | };
352 | name = Release;
353 | };
354 | 5B891C0A2222EC47002F31C6 /* Debug */ = {
355 | isa = XCBuildConfiguration;
356 | buildSettings = {
357 | APPLICATION_EXTENSION_API_ONLY = YES;
358 | CLANG_ENABLE_MODULES = YES;
359 | CODE_SIGN_IDENTITY = "";
360 | CODE_SIGN_STYLE = Manual;
361 | DEFINES_MODULE = YES;
362 | DEVELOPMENT_TEAM = "";
363 | DYLIB_COMPATIBILITY_VERSION = 1;
364 | DYLIB_CURRENT_VERSION = 1;
365 | DYLIB_INSTALL_NAME_BASE = "@rpath";
366 | INFOPLIST_FILE = froop/Info.plist;
367 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
368 | LD_RUNPATH_SEARCH_PATHS = (
369 | "$(inherited)",
370 | "@executable_path/Frameworks",
371 | "@loader_path/Frameworks",
372 | );
373 | PRODUCT_BUNDLE_IDENTIFIER = io.lookback.froop;
374 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
375 | PROVISIONING_PROFILE_SPECIFIER = "";
376 | SKIP_INSTALL = YES;
377 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
378 | SWIFT_VERSION = 5.0;
379 | TARGETED_DEVICE_FAMILY = "1,2";
380 | };
381 | name = Debug;
382 | };
383 | 5B891C0B2222EC47002F31C6 /* Release */ = {
384 | isa = XCBuildConfiguration;
385 | buildSettings = {
386 | APPLICATION_EXTENSION_API_ONLY = YES;
387 | CLANG_ENABLE_MODULES = YES;
388 | CODE_SIGN_IDENTITY = "";
389 | CODE_SIGN_STYLE = Manual;
390 | DEFINES_MODULE = YES;
391 | DEVELOPMENT_TEAM = "";
392 | DYLIB_COMPATIBILITY_VERSION = 1;
393 | DYLIB_CURRENT_VERSION = 1;
394 | DYLIB_INSTALL_NAME_BASE = "@rpath";
395 | INFOPLIST_FILE = froop/Info.plist;
396 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
397 | LD_RUNPATH_SEARCH_PATHS = (
398 | "$(inherited)",
399 | "@executable_path/Frameworks",
400 | "@loader_path/Frameworks",
401 | );
402 | PRODUCT_BUNDLE_IDENTIFIER = io.lookback.froop;
403 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
404 | PROVISIONING_PROFILE_SPECIFIER = "";
405 | SKIP_INSTALL = YES;
406 | SWIFT_VERSION = 5.0;
407 | TARGETED_DEVICE_FAMILY = "1,2";
408 | };
409 | name = Release;
410 | };
411 | 5B891C0D2222EC47002F31C6 /* Debug */ = {
412 | isa = XCBuildConfiguration;
413 | buildSettings = {
414 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
415 | CODE_SIGN_STYLE = Automatic;
416 | DEVELOPMENT_TEAM = 62TZ9933HE;
417 | INFOPLIST_FILE = froopTests/Info.plist;
418 | LD_RUNPATH_SEARCH_PATHS = (
419 | "$(inherited)",
420 | "@executable_path/Frameworks",
421 | "@loader_path/Frameworks",
422 | );
423 | PRODUCT_BUNDLE_IDENTIFIER = io.lookback.froopTests;
424 | PRODUCT_NAME = "$(TARGET_NAME)";
425 | SWIFT_VERSION = 5.0;
426 | TARGETED_DEVICE_FAMILY = "1,2";
427 | };
428 | name = Debug;
429 | };
430 | 5B891C0E2222EC47002F31C6 /* Release */ = {
431 | isa = XCBuildConfiguration;
432 | buildSettings = {
433 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
434 | CODE_SIGN_STYLE = Automatic;
435 | DEVELOPMENT_TEAM = 62TZ9933HE;
436 | INFOPLIST_FILE = froopTests/Info.plist;
437 | LD_RUNPATH_SEARCH_PATHS = (
438 | "$(inherited)",
439 | "@executable_path/Frameworks",
440 | "@loader_path/Frameworks",
441 | );
442 | PRODUCT_BUNDLE_IDENTIFIER = io.lookback.froopTests;
443 | PRODUCT_NAME = "$(TARGET_NAME)";
444 | SWIFT_VERSION = 5.0;
445 | TARGETED_DEVICE_FAMILY = "1,2";
446 | };
447 | name = Release;
448 | };
449 | /* End XCBuildConfiguration section */
450 |
451 | /* Begin XCConfigurationList section */
452 | 5B891BEF2222EC46002F31C6 /* Build configuration list for PBXProject "froop" */ = {
453 | isa = XCConfigurationList;
454 | buildConfigurations = (
455 | 5B891C072222EC47002F31C6 /* Debug */,
456 | 5B891C082222EC47002F31C6 /* Release */,
457 | );
458 | defaultConfigurationIsVisible = 0;
459 | defaultConfigurationName = Release;
460 | };
461 | 5B891C092222EC47002F31C6 /* Build configuration list for PBXNativeTarget "froop" */ = {
462 | isa = XCConfigurationList;
463 | buildConfigurations = (
464 | 5B891C0A2222EC47002F31C6 /* Debug */,
465 | 5B891C0B2222EC47002F31C6 /* Release */,
466 | );
467 | defaultConfigurationIsVisible = 0;
468 | defaultConfigurationName = Release;
469 | };
470 | 5B891C0C2222EC47002F31C6 /* Build configuration list for PBXNativeTarget "froopTests" */ = {
471 | isa = XCConfigurationList;
472 | buildConfigurations = (
473 | 5B891C0D2222EC47002F31C6 /* Debug */,
474 | 5B891C0E2222EC47002F31C6 /* Release */,
475 | );
476 | defaultConfigurationIsVisible = 0;
477 | defaultConfigurationName = Release;
478 | };
479 | /* End XCConfigurationList section */
480 | };
481 | rootObject = 5B891BEC2222EC46002F31C6 /* Project object */;
482 | }
483 |
--------------------------------------------------------------------------------
/froop.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/froop.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/froop.xcodeproj/xcshareddata/xcbaselines/5B891BFD2222EC47002F31C6.xcbaseline/C6951AF0-5BDC-4962-A4A0-BEC937992614.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | classNames
6 |
7 | froopTests
8 |
9 | testPerformanceMap()
10 |
11 | com.apple.XCTPerformanceMetric_WallClockTime
12 |
13 | baselineAverage
14 | 2.08e-05
15 | baselineIntegrationDisplayName
16 | Local Baseline
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/froop.xcodeproj/xcshareddata/xcbaselines/5B891BFD2222EC47002F31C6.xcbaseline/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | runDestinationsByUUID
6 |
7 | C6951AF0-5BDC-4962-A4A0-BEC937992614
8 |
9 | localComputer
10 |
11 | busSpeedInMHz
12 | 100
13 | cpuCount
14 | 1
15 | cpuKind
16 | Intel Core i7
17 | cpuSpeedInMHz
18 | 3300
19 | logicalCPUCoresPerPackage
20 | 4
21 | modelCode
22 | MacBookPro13,2
23 | physicalCPUCoresPerPackage
24 | 2
25 | platformIdentifier
26 | com.apple.platform.macosx
27 |
28 | targetArchitecture
29 | x86_64
30 | targetDevice
31 |
32 | modelCode
33 | iPhone11,8
34 | platformIdentifier
35 | com.apple.platform.iphonesimulator
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/froop.xcodeproj/xcshareddata/xcschemes/froop.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
42 |
48 |
49 |
50 |
51 |
52 |
62 |
63 |
69 |
70 |
71 |
72 |
78 |
79 |
85 |
86 |
87 |
88 |
90 |
91 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/froop/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 |
22 |
23 |
--------------------------------------------------------------------------------
/froop/Threadly.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Threadly.swift
3 | // Threadly
4 | //
5 | // The MIT License (MIT)
6 | //
7 | // Copyright (c) 2017 Nikolai Vazquez
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 | //
27 |
28 | import Foundation
29 |
30 | private final class _Key {
31 | var raw: pthread_key_t
32 |
33 | var box: Box? {
34 | guard let pointer = pthread_getspecific(raw) else {
35 | return nil
36 | }
37 | return Unmanaged>.fromOpaque(pointer).takeUnretainedValue()
38 | }
39 |
40 | init() {
41 | raw = pthread_key_t()
42 | pthread_key_create(&raw) {
43 | // Cast required because argument is optional on some
44 | // platforms (Linux) but not on others (macOS)
45 | guard let rawPointer = ($0 as UnsafeMutableRawPointer?) else {
46 | return
47 | }
48 | Unmanaged.fromOpaque(rawPointer).release()
49 | }
50 | }
51 |
52 | deinit {
53 | pthread_key_delete(raw)
54 | }
55 |
56 | func box(create: () throws -> T) rethrows -> Box {
57 | if let box = self.box {
58 | return box
59 | } else {
60 | let box = try Box(create())
61 | pthread_setspecific(raw, Unmanaged.passRetained(box).toOpaque())
62 | return box
63 | }
64 | }
65 | }
66 |
67 | /// A reference to a heap-allocated value.
68 | final class Box {
69 | /// The boxed value.
70 | var value: Value
71 |
72 | /// Creates an instance that boxes `value`.
73 | init(_ value: Value) {
74 | self.value = value
75 | }
76 | }
77 |
78 | /// A type that takes an initializer to create and then store a value that's
79 | /// unique to the current thread. The initializer is called the first time
80 | /// the thread-local is accessed, either through `inner` or `withValue(_:)`.
81 | ///
82 | /// - note: If the initial value isn't known until retrieval, use `DeferredThreadLocal`.
83 | public struct ThreadLocal: Hashable {
84 | fileprivate var _def: DeferredThreadLocal
85 |
86 | private var _create: () -> Value
87 |
88 | /// The hash value.
89 | public func hash(into hasher: inout Hasher) {
90 | hasher.combine(_def.hashValue)
91 | }
92 |
93 | /// Returns the inner boxed value for the current thread.
94 | var inner: Box {
95 | return _def.inner(createdWith: _create)
96 | }
97 |
98 | /// Creates an instance that will use `value` captured in its current
99 | /// state for an initial value.
100 | ///
101 | /// Sometimes this is what you want such as in cases where `value` is
102 | /// the result of an expensive operation or a copy-on-write type like
103 | /// `Array` or `Dictionary`.
104 | init(capturing value: Value) {
105 | self.init { [value] in
106 | value
107 | }
108 | }
109 |
110 | /// Creates an instance that will use `value` for an initial value.
111 | init(value: @escaping @autoclosure () -> Value) {
112 | self.init(create: value)
113 | }
114 |
115 | /// Creates an instance that will use `create` to generate an initial value.
116 | public init(create: @escaping () -> Value) {
117 | _create = create
118 | _def = DeferredThreadLocal()
119 | }
120 |
121 | /// Creates an instance that uses the same storage as `deferred` but with
122 | /// `create` as an initializer.
123 | init(fromDeferred deferred: DeferredThreadLocal, create: @escaping () -> Value) {
124 | _create = create
125 | _def = deferred
126 | }
127 |
128 | /// Returns the result of the closure performed on the value of `self`.
129 | public func withValue(_ body: (inout Value) throws -> T) rethrows -> T {
130 | return try body(&inner.value)
131 | }
132 | }
133 |
134 | /// A type that stores a value unique to the current thread. An initial value
135 | /// isn't provided until the inner thread-local value is accessed.
136 | ///
137 | /// - note: If the initial value is known at the time of initialization of the
138 | /// enclosing type, consider using `ThreadLocal` instead.
139 | struct DeferredThreadLocal: Hashable {
140 | fileprivate var _key: _Key
141 |
142 | /// The hash value.
143 | public func hash(into hasher: inout Hasher) {
144 | hasher.combine(_key.raw.hashValue)
145 | }
146 |
147 | /// Returns the inner boxed value for the current thread if it's been
148 | /// created, or `nil` otherwise.
149 | var inner: Box? {
150 | return _key.box
151 | }
152 |
153 | /// Creates an instance.
154 | init() {
155 | _key = _Key()
156 | }
157 |
158 | /// Returns the inner boxed value for the current thread,
159 | /// created with `create` if not previously initialized.
160 | func inner(createdWith create: () throws -> Value) rethrows -> Box {
161 | return try _key.box(create: create)
162 | }
163 |
164 | /// Returns the result of the closure performed on the inner thread-local
165 | /// value of `self`, or `nil` if uninitialized.
166 | func withValue(_ body: (inout Value) throws -> T) rethrows -> T? {
167 | return try inner.map { try body(&$0.value) }
168 | }
169 |
170 | /// Returns the result of the closure performed on the inner thread-local
171 | /// value of `self`, created with `create` if not previously initialized.
172 | func withValue(createdWith create: () throws -> Value, _ body: (inout Value) throws -> T) rethrows -> T {
173 | return try body(&inner(createdWith: create).value)
174 | }
175 | }
176 |
177 | /// A type that has a static thread-local instance.
178 | protocol ThreadLocalRetrievable {
179 | /// The thread-local boxed instance of `Self`.
180 | static var threadLocal: Box { get }
181 |
182 | /// Returns the result of performing the closure on the thread-local instance of `Self`.
183 | static func withThreadLocal(_ body: (inout Self) throws -> T) rethrows -> T
184 | }
185 |
186 | extension ThreadLocalRetrievable {
187 | /// Returns the result of performing the closure on the thread-local instance of `Self`.
188 | static func withThreadLocal(_ body: (inout Self) throws -> T) rethrows -> T {
189 | return try body(&threadLocal.value)
190 | }
191 | }
192 |
193 | /// Returns a Boolean value that indicates whether the two arguments have equal values.
194 | public func == (lhs: ThreadLocal, rhs: ThreadLocal) -> Bool {
195 | return lhs._def == rhs._def
196 | }
197 |
198 | /// Returns a Boolean value that indicates whether the two arguments have equal values.
199 | func == (lhs: DeferredThreadLocal, rhs: DeferredThreadLocal) -> Bool {
200 | return lhs._key.raw == rhs._key.raw
201 | }
202 |
--------------------------------------------------------------------------------
/froop/froop.h:
--------------------------------------------------------------------------------
1 | //
2 | // froop.h
3 | // froop
4 | //
5 | // Created by martin on 2019-02-24.
6 | // Copyright © 2019 Lookback Ltd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for froop.
12 | FOUNDATION_EXPORT double froopVersionNumber;
13 |
14 | //! Project version string for froop.
15 | FOUNDATION_EXPORT const unsigned char froopVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/froopTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/gen-docs.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -x
4 |
5 | jazzy --clean --author Lookback --author_url https://lookback.io --github_url https://github.com/lookback/froop-swift --module froop --output docs/
6 |
--------------------------------------------------------------------------------