File tree Expand file tree Collapse file tree 6 files changed +171
-0
lines changed
.swiftpm/xcode/package.xcworkspace/xcshareddata Expand file tree Collapse file tree 6 files changed +171
-0
lines changed Original file line number Diff line number Diff line change
1
+ .DS_Store
2
+ /.build
3
+ /Packages
4
+ /* .xcodeproj
5
+ xcuserdata /
6
+ DerivedData /
7
+ .swiftpm /xcode /package.xcworkspace /contents.xcworkspacedata
Original file line number Diff line number Diff line change
1
+ <?xml version =" 1.0" encoding =" UTF-8" ?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version =" 1.0" >
4
+ <dict >
5
+ <key >IDEDidComputeMac32BitWarning </key >
6
+ <true />
7
+ </dict >
8
+ </plist >
Original file line number Diff line number Diff line change
1
+ // swift-tools-version:5.5
2
+ // The swift-tools-version declares the minimum version of Swift required to build this package.
3
+
4
+ import PackageDescription
5
+
6
+ let package = Package (
7
+ name: " Closure " ,
8
+ products: [
9
+ . library(
10
+ name: " Closure " ,
11
+ targets: [ " Closure " ]
12
+ ) ,
13
+ ] ,
14
+ targets: [
15
+ . target(
16
+ name: " Closure " ,
17
+ dependencies: [ ]
18
+ ) ,
19
+ . testTarget(
20
+ name: " ClosureTests " ,
21
+ dependencies: [ " Closure " ]
22
+ ) ,
23
+ ]
24
+ )
Original file line number Diff line number Diff line change
1
+ # Closure
2
+
3
+ * Define and chain Closures with Inputs and Outputs*
4
+
5
+
6
+ ## Examples
7
+
8
+ ** No Scoped State**
9
+ ``` swift
10
+ let noStateCount = Closure< String , String > { text in
11
+ String (repeating : text, count : 4 )
12
+ }
13
+ .then { string in
14
+ Int (string) ?? 0
15
+ }
16
+
17
+
18
+ XCTAssertEqual (noStateCount.method (" 5" ), 5555 )
19
+ XCTAssertEqual (noStateCount.method (" 5" ), 5555 )
20
+ XCTAssertEqual (noStateCount.method (" 5" ), 5555 )
21
+ ```
22
+
23
+ ** Scoped State**
24
+ ``` swift
25
+ let stateCount: Closure<String , Int > = Closure< String , String > {
26
+ var count = 1
27
+
28
+ return { text in
29
+ defer {
30
+ count += 1
31
+ }
32
+
33
+ return String (repeating : text, count : count)
34
+ }
35
+ }
36
+ .then { string in
37
+ Int (string) ?? 0
38
+ }
39
+
40
+ XCTAssertEqual (stateCount.method (" 5" ), 5 )
41
+ XCTAssertEqual (stateCount.method (" 5" ), 55 )
42
+ XCTAssertEqual (stateCount.method (" 5" ), 555 )
43
+ ```
Original file line number Diff line number Diff line change
1
+ /// A Struct that defines a Closure with a given Input and a given Output
2
+ public struct Closure < Input, Output> {
3
+ /// The Closure passed in during initialization
4
+ public let method : ( Input ) -> Output
5
+
6
+ /// Initialize a Closure without any scoped state
7
+ public init (
8
+ _ closure: @escaping ( Input ) -> Output
9
+ ) {
10
+ method = closure
11
+ }
12
+
13
+ /// Initialize a Closure with potential scoped state
14
+ public init (
15
+ _ closure: ( ) -> ( ( Input ) -> Output )
16
+ ) {
17
+ method = closure ( )
18
+ }
19
+ }
20
+
21
+ public extension Closure {
22
+ /// Return Void as the final Output
23
+ var toVoid : Closure < Input , Void > {
24
+ Closure < Input , Void > { input in
25
+ _ = method ( input)
26
+
27
+ return ( )
28
+ }
29
+ }
30
+
31
+ /// Chain another Closure with a NewOutput
32
+ func then< NewOutput> (
33
+ _ closure: @escaping ( Output ) -> NewOutput
34
+ ) -> Closure < Input , NewOutput > {
35
+ Closure < Input , NewOutput > { input in
36
+ closure ( method ( input) )
37
+ }
38
+ }
39
+
40
+ /// Run the Closure with Input and a Completion Handler
41
+ func run(
42
+ input: Input ,
43
+ onCompletion onCompletionHandler: ( ) -> Void = { }
44
+ ) -> Output {
45
+ defer {
46
+ onCompletionHandler ( )
47
+ }
48
+ return method ( input)
49
+ }
50
+ }
Original file line number Diff line number Diff line change
1
+ import XCTest
2
+ @testable import Closure
3
+
4
+ final class ClosureTests : XCTestCase {
5
+ func testClosure( ) throws {
6
+ let noStateCount = Closure < String , String > { text in
7
+ String ( repeating: text, count: 4 )
8
+ }
9
+ . then { string in
10
+ Int ( string) ?? 0
11
+ }
12
+
13
+
14
+ XCTAssertEqual ( noStateCount. method ( " 5 " ) , 5555 )
15
+ XCTAssertEqual ( noStateCount. method ( " 5 " ) , 5555 )
16
+ XCTAssertEqual ( noStateCount. method ( " 5 " ) , 5555 )
17
+ }
18
+
19
+ func testStateClosure( ) throws {
20
+ let stateCount : Closure < String , Int > = Closure < String , String > {
21
+ var count = 1
22
+
23
+ return { text in
24
+ defer {
25
+ count += 1
26
+ }
27
+
28
+ return String ( repeating: text, count: count)
29
+ }
30
+ }
31
+ . then { string in
32
+ Int ( string) ?? 0
33
+ }
34
+
35
+ XCTAssertEqual ( stateCount. method ( " 5 " ) , 5 )
36
+ XCTAssertEqual ( stateCount. method ( " 5 " ) , 55 )
37
+ XCTAssertEqual ( stateCount. method ( " 5 " ) , 555 )
38
+ }
39
+ }
You can’t perform that action at this time.
0 commit comments