Skip to content

Commit e37b966

Browse files
committed
Merge pull request #19 from kareman/parameterize
Merge master with parameterize branch.
2 parents 914f562 + 5c9d5da commit e37b966

File tree

5 files changed

+58
-89
lines changed

5 files changed

+58
-89
lines changed

LlamaKit.xcodeproj/project.pbxproj

-20
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,6 @@
1515
FB2F8D8719BF637B00E4C49E /* LlamaKit.h in Headers */ = {isa = PBXBuildFile; fileRef = FB2F8D8619BF637B00E4C49E /* LlamaKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
1616
FB2F8D9119BF637B00E4C49E /* ResultTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB2F8D9019BF637B00E4C49E /* ResultTests.swift */; };
1717
FB2F8D9B19BF661000E4C49E /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB2F8D9A19BF661000E4C49E /* Result.swift */; };
18-
FBA7F02B19DA0D0D00A6BD2E /* Box.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBA7F02A19DA0D0D00A6BD2E /* Box.swift */; };
19-
FBA7F02C19DA0D0D00A6BD2E /* Box.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBA7F02A19DA0D0D00A6BD2E /* Box.swift */; };
20-
FBA7F02D19DA0D0D00A6BD2E /* Box.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBA7F02A19DA0D0D00A6BD2E /* Box.swift */; };
21-
FBA7F02E19DA0D0D00A6BD2E /* Box.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBA7F02A19DA0D0D00A6BD2E /* Box.swift */; };
22-
FBA7F03019DA0D2E00A6BD2E /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBA7F02F19DA0D2E00A6BD2E /* Error.swift */; };
23-
FBA7F03119DA0D2E00A6BD2E /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBA7F02F19DA0D2E00A6BD2E /* Error.swift */; };
24-
FBA7F03219DA0D2E00A6BD2E /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBA7F02F19DA0D2E00A6BD2E /* Error.swift */; };
25-
FBA7F03319DA0D2E00A6BD2E /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBA7F02F19DA0D2E00A6BD2E /* Error.swift */; };
2618
/* End PBXBuildFile section */
2719

2820
/* Begin PBXContainerItemProxy section */
@@ -53,8 +45,6 @@
5345
FB2F8D9019BF637B00E4C49E /* ResultTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultTests.swift; sourceTree = "<group>"; };
5446
FB2F8D9A19BF661000E4C49E /* Result.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Result.swift; sourceTree = "<group>"; };
5547
FB7C6F3D19D61C230087DA98 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
56-
FBA7F02A19DA0D0D00A6BD2E /* Box.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Box.swift; sourceTree = "<group>"; };
57-
FBA7F02F19DA0D2E00A6BD2E /* Error.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Error.swift; sourceTree = "<group>"; };
5848
/* End PBXFileReference section */
5949

6050
/* Begin PBXFrameworksBuildPhase section */
@@ -119,8 +109,6 @@
119109
children = (
120110
FB2F8D8619BF637B00E4C49E /* LlamaKit.h */,
121111
FB2F8D9A19BF661000E4C49E /* Result.swift */,
122-
FBA7F02A19DA0D0D00A6BD2E /* Box.swift */,
123-
FBA7F02F19DA0D2E00A6BD2E /* Error.swift */,
124112
FB2F8D8419BF637B00E4C49E /* Supporting Files */,
125113
);
126114
path = LlamaKit;
@@ -326,8 +314,6 @@
326314
buildActionMask = 2147483647;
327315
files = (
328316
D0297D2A19D679B8009986A9 /* Result.swift in Sources */,
329-
FBA7F03219DA0D2E00A6BD2E /* Error.swift in Sources */,
330-
FBA7F02D19DA0D0D00A6BD2E /* Box.swift in Sources */,
331317
);
332318
runOnlyForDeploymentPostprocessing = 0;
333319
};
@@ -336,8 +322,6 @@
336322
buildActionMask = 2147483647;
337323
files = (
338324
D0297D2B19D679C0009986A9 /* ResultTests.swift in Sources */,
339-
FBA7F03319DA0D2E00A6BD2E /* Error.swift in Sources */,
340-
FBA7F02E19DA0D0D00A6BD2E /* Box.swift in Sources */,
341325
);
342326
runOnlyForDeploymentPostprocessing = 0;
343327
};
@@ -346,8 +330,6 @@
346330
buildActionMask = 2147483647;
347331
files = (
348332
FB2F8D9B19BF661000E4C49E /* Result.swift in Sources */,
349-
FBA7F03019DA0D2E00A6BD2E /* Error.swift in Sources */,
350-
FBA7F02B19DA0D0D00A6BD2E /* Box.swift in Sources */,
351333
);
352334
runOnlyForDeploymentPostprocessing = 0;
353335
};
@@ -356,8 +338,6 @@
356338
buildActionMask = 2147483647;
357339
files = (
358340
FB2F8D9119BF637B00E4C49E /* ResultTests.swift in Sources */,
359-
FBA7F03119DA0D2E00A6BD2E /* Error.swift in Sources */,
360-
FBA7F02C19DA0D0D00A6BD2E /* Box.swift in Sources */,
361341
);
362342
runOnlyForDeploymentPostprocessing = 0;
363343
};

LlamaKit/Box.swift

-10
This file was deleted.

LlamaKit/Error.swift

-15
This file was deleted.

LlamaKit/Result.swift

+32-19
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import Foundation
88
/// A success `Result` returning `value`
99
/// This form is preferred to `Result.Success(Box(value))` because it
1010
// does not require dealing with `Box()`
11-
public func success<T>(value: T) -> Result<T> {
11+
public func success<T,E>(value: T) -> Result<T,E> {
1212
return .Success(Box(value))
1313
}
1414

@@ -21,6 +21,10 @@ public func success<T>(value: T) -> Result<T> {
2121
/// let fail: Result<Int> = failure()
2222
///
2323

24+
/// Dictionary keys for default errors
25+
public let ErrorFileKey = "LMErrorFile"
26+
public let ErrorLineKey = "LMErrorLine"
27+
2428
private func defaultError(userInfo: [NSObject: AnyObject]) -> NSError {
2529
return NSError(domain: "", code: 0, userInfo: userInfo)
2630
}
@@ -33,35 +37,37 @@ private func defaultError(file: String = __FILE__, line: Int = __LINE__) -> NSEr
3337
return defaultError([ErrorFileKey: file, ErrorLineKey: line])
3438
}
3539

36-
public func failure<T>(message: String, file: String = __FILE__, line: Int = __LINE__) -> Result<T> {
37-
return failure(defaultError(message, file: file, line: line))
40+
public func failure<T>(message: String, file: String = __FILE__, line: Int = __LINE__) -> Result<T,NSError> {
41+
let userInfo: [NSObject : AnyObject] = [NSLocalizedDescriptionKey: message, ErrorFileKey: file, ErrorLineKey: line]
42+
return failure(defaultError(userInfo))
3843
}
3944

40-
public func failure<T>(file: String = __FILE__, line: Int = __LINE__) -> Result<T> {
41-
return failure(defaultError(file: file, line: line))
45+
public func failure<T>(file: String = __FILE__, line: Int = __LINE__) -> Result<T,NSError> {
46+
let userInfo: [NSObject : AnyObject] = [ErrorFileKey: file, ErrorLineKey: line]
47+
return failure(defaultError(userInfo))
4248
}
4349

44-
public func failure<T>(error: ErrorType) -> Result<T> {
45-
return .Failure(error)
50+
public func failure<T,E>(error: E) -> Result<T,E> {
51+
return .Failure(Box(error))
4652
}
4753

4854
/// Construct a `Result` using a block which receives an error parameter.
4955
/// Expected to return non-nil for success.
5056

51-
public func try<T>(f: NSErrorPointer -> T?, file: String = __FILE__, line: Int = __LINE__) -> Result<T> {
57+
public func try<T>(f: NSErrorPointer -> T?, file: String = __FILE__, line: Int = __LINE__) -> Result<T,NSError> {
5258
var error: NSError?
5359
return f(&error).map(success) ?? failure(error ?? defaultError(file: file, line: line))
5460
}
5561

56-
public func try(f: NSErrorPointer -> Bool, file: String = __FILE__, line: Int = __LINE__) -> Result<()> {
62+
public func try(f: NSErrorPointer -> Bool, file: String = __FILE__, line: Int = __LINE__) -> Result<(),NSError> {
5763
var error: NSError?
5864
return f(&error) ? success(()) : failure(error ?? defaultError(file: file, line: line))
5965
}
6066

61-
/// Container for a successful value (T) or a failure with an NSError
62-
public enum Result<T> {
67+
/// Container for a successful value (T) or a failure with an E
68+
public enum Result<T,E> {
6369
case Success(Box<T>)
64-
case Failure(ErrorType)
70+
case Failure(Box<E>)
6571

6672
/// The successful value as an Optional
6773
public var value: T? {
@@ -72,10 +78,10 @@ public enum Result<T> {
7278
}
7379

7480
/// The failing error as an Optional
75-
public var error: ErrorType? {
81+
public var error: E? {
7682
switch self {
7783
case .Success: return nil
78-
case .Failure(let err): return err
84+
case .Failure(let err): return err.unbox
7985
}
8086
}
8187

@@ -88,7 +94,7 @@ public enum Result<T> {
8894

8995
/// Return a new result after applying a transformation to a successful value.
9096
/// Mapping a failure returns a new failure without evaluating the transform
91-
public func map<U>(transform: T -> U) -> Result<U> {
97+
public func map<U>(transform: T -> U) -> Result<U,E> {
9298
switch self {
9399
case Success(let box):
94100
return .Success(Box(transform(box.unbox)))
@@ -99,8 +105,8 @@ public enum Result<T> {
99105

100106
/// Return a new result after applying a transformation (that itself
101107
/// returns a result) to a successful value.
102-
/// Flat mapping a failure returns a new failure without evaluating the transform
103-
public func flatMap<U>(transform:T -> Result<U>) -> Result<U> {
108+
/// Calling with a failure returns a new failure without evaluating the transform
109+
public func flatMap<U>(transform:T -> Result<U,E>) -> Result<U,E> {
104110
switch self {
105111
case Success(let value): return transform(value.unbox)
106112
case Failure(let error): return .Failure(error)
@@ -114,19 +120,26 @@ extension Result: Printable {
114120
case .Success(let box):
115121
return "Success: \(box.unbox)"
116122
case .Failure(let error):
117-
return "Failure: \(error)"
123+
return "Failure: \(error.unbox)"
118124
}
119125
}
120126
}
121127

122128
/// Failure coalescing
123129
/// .Success(Box(42)) ?? 0 ==> 42
124130
/// .Failure(NSError()) ?? 0 ==> 0
125-
public func ??<T>(result: Result<T>, defaultValue: @autoclosure () -> T) -> T {
131+
public func ??<T,E>(result: Result<T,E>, defaultValue: @autoclosure () -> T) -> T {
126132
switch result {
127133
case .Success(let value):
128134
return value.unbox
129135
case .Failure(let error):
130136
return defaultValue()
131137
}
132138
}
139+
140+
/// Due to current swift limitations, we have to include this Box in Result.
141+
/// Swift cannot handle an enum with multiple associated data (A, NSError) where one is of unknown size (A)
142+
final public class Box<T> {
143+
public let unbox: T
144+
public init(_ value: T) { self.unbox = value }
145+
}

LlamaKitTests/ResultTests.swift

+26-25
Original file line numberDiff line numberDiff line change
@@ -15,104 +15,105 @@ class ResultTests: XCTestCase {
1515
let err2 = NSError(domain: "", code: 12, userInfo: nil)
1616

1717
func testSuccessIsSuccess() {
18-
let s = success(42)
18+
let s: Result<Int,NSError> = success(42)
1919
XCTAssertTrue(s.isSuccess)
2020
}
2121

2222
func testFailureIsNotSuccess() {
23-
let f: Result<Bool> = failure()
23+
let f: Result<Bool, NSError> = failure()
2424
XCTAssertFalse(f.isSuccess)
2525
}
2626

2727
func testSuccessReturnsValue() {
28-
let s = success(42)
28+
let s: Result<Int,NSError> = success(42)
2929
XCTAssertEqual(s.value!, 42)
3030
}
3131

3232
func testSuccessReturnsNoError() {
33-
let s = success(42)
33+
let s: Result<Int,NSError> = success(42)
3434
XCTAssert(s.error == nil)
3535
}
3636

3737
func testFailureReturnsError() {
38-
let f: Result<Int> = failure(self.err)
39-
XCTAssertEqual(f.error as NSError, self.err)
38+
let f: Result<Int, NSError> = failure(self.err)
39+
XCTAssertEqual(f.error!, self.err)
4040
}
4141

4242
func testFailureReturnsNoValue() {
43-
let f: Result<Int> = failure(self.err)
43+
let f: Result<Int, NSError> = failure(self.err)
4444
XCTAssertNil(f.value)
4545
}
4646

4747
func testMapSuccessUnaryOperator() {
48-
let x = success(42)
48+
let x: Result<Int, NSError> = success(42)
4949
let y = x.map(-)
5050
XCTAssertEqual(y.value!, -42)
5151
}
5252

5353
func testMapFailureUnaryOperator() {
54-
let x: Result<Int> = failure(self.err)
54+
let x: Result<Int, NSError> = failure(self.err)
5555
let y = x.map(-)
5656
XCTAssertNil(y.value)
57-
XCTAssertEqual(y.error as NSError, self.err)
57+
XCTAssertEqual(y.error!, self.err)
5858
}
5959

6060
func testMapSuccessNewType() {
61-
let x = success("abcd")
61+
let x: Result<String, NSError> = success("abcd")
6262
let y = x.map { countElements($0) }
6363
XCTAssertEqual(y.value!, 4)
6464
}
6565

6666
func testMapFailureNewType() {
67-
let x: Result<String> = failure(self.err)
67+
let x: Result<String, NSError> = failure(self.err)
6868
let y = x.map { countElements($0) }
69-
XCTAssertEqual(y.error as NSError, self.err)
69+
XCTAssertEqual(y.error!, self.err)
7070
}
7171

72-
func doubleSuccess(x: Int) -> Result<Int> {
72+
func doubleSuccess(x: Int) -> Result<Int, NSError> {
7373
return success(x * 2)
7474
}
7575

76-
func doubleFailure(x: Int) -> Result<Int> {
76+
func doubleFailure(x: Int) -> Result<Int, NSError> {
7777
return failure(self.err)
7878
}
7979

8080
func testFlatMapSuccessSuccess() {
81-
let x = success(42)
81+
let x: Result<Int, NSError> = success(42)
8282
let y = x.flatMap(doubleSuccess)
8383
XCTAssertEqual(y.value!, 84)
8484
}
8585

8686
func testFlatMapSuccessFailure() {
87-
let x = success(42)
87+
let x: Result<Int, NSError> = success(42)
8888
let y = x.flatMap(doubleFailure)
89-
XCTAssertEqual(y.error as NSError, self.err)
89+
XCTAssertEqual(y.error!, self.err)
9090
}
9191

9292
func testFlatMapFailureSuccess() {
93-
let x: Result<Int> = failure(self.err2)
93+
let x: Result<Int, NSError> = failure(self.err2)
9494
let y = x.flatMap(doubleSuccess)
95-
XCTAssertEqual(y.error as NSError, self.err2)
95+
XCTAssertEqual(y.error!, self.err2)
9696
}
9797

9898
func testFlatMapFailureFailure() {
99-
let x: Result<Int> = failure(self.err2)
99+
let x: Result<Int, NSError> = failure(self.err2)
100100
let y = x.flatMap(doubleFailure)
101-
XCTAssertEqual(y.error as NSError, self.err2)
101+
XCTAssertEqual(y.error!, self.err2)
102102
}
103103

104104
func testDescriptionSuccess() {
105-
let x = success(42)
105+
let x: Result<Int, NSError> = success(42)
106106
XCTAssertEqual(x.description, "Success: 42")
107107
}
108108

109109
func testDescriptionFailure() {
110-
let x: Result<String> = failure()
110+
let x: Result<String, NSError> = failure()
111111
XCTAssert(x.description.hasPrefix("Failure: Error Domain= Code=0 "))
112112
}
113113

114114
func testCoalesceSuccess() {
115-
let x = success(42) ?? 43
115+
let r: Result<Int, NSError> = success(42)
116+
let x = r ?? 43
116117
XCTAssertEqual(x, 42)
117118
}
118119

0 commit comments

Comments
 (0)