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