-
Notifications
You must be signed in to change notification settings - Fork 0
/
With.swift
45 lines (35 loc) · 1.69 KB
/
With.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// With
// @author: Slipp Douglas Thompson
// @license: Public Domain per The Unlicense. See accompanying LICENSE file or <http://unlicense.org/>.
// MARK: Ref-Type, Returning Subject
/// “With” on an reference-type (object) subject, returning the same subject (including any mutations performed in the closure).
///
/// Unfortunately, we need to use `inout` for the `operations` closure here, so that the arguments exactly match the value-type (`SubjectT:Any`) version further down— we get a _“Ambiguous use of 'with'”_ error if the `inout` isn't in there.
/// (I believe Swift only lets us overload a function with a distinct ref-type version and a value-type version when the arguments match exactly)
@inlinable @discardableResult
public func with<SubjectT:AnyObject>(_ subject:SubjectT, operations:(inout SubjectT) throws -> Void)
rethrows -> SubjectT
{
var subject = subject
try operations(&subject)
return subject
}
// MARK: Ref-Type, Returning Arbitrary Value
/// “With” on an reference-type (object) subject, returning an aribitrary return value from the closure (the subject is still mutated).
@inlinable
public func with<SubjectT:AnyObject, ReturnT:Any>(_ subject:SubjectT, operations:(inout SubjectT) throws -> ReturnT)
rethrows -> ReturnT
{
var subject = subject
return try operations(&subject)
}
// MARK: Value-Type, Returning Subject
/// “With” on an value-type (struct, enum) subject, returning the same subject (technically a copy, including any mutations performed in the closure).
@inlinable
public func with<SubjectT:Any>(_ subject:SubjectT, operations:(inout SubjectT) throws -> Void)
rethrows -> SubjectT
{
var subject = subject
try operations(&subject)
return subject
}