├── PartialOperatorApplication.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── project.pbxproj ├── PartialOperatorApplication ├── PartialOperatorApplication.h └── Info.plist ├── PartialOperatorApplicationTests ├── Info.plist └── PartialOperatorApplicationTests.swift ├── .gitignore ├── README.md └── Sources └── PartialOperatorApplication.swift /PartialOperatorApplication.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /PartialOperatorApplication/PartialOperatorApplication.h: -------------------------------------------------------------------------------- 1 | // 2 | // PartialOperatorApplication.h 3 | // PartialOperatorApplication 4 | // 5 | // Created by Michael Pangburn on 2/5/18. 6 | // Copyright © 2018 Michael Pangburn. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for PartialOperatorApplication. 12 | FOUNDATION_EXPORT double PartialOperatorApplicationVersionNumber; 13 | 14 | //! Project version string for PartialOperatorApplication. 15 | FOUNDATION_EXPORT const unsigned char PartialOperatorApplicationVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /PartialOperatorApplicationTests/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 | -------------------------------------------------------------------------------- /PartialOperatorApplication/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 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /.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 | # Carthage 52 | # 53 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 54 | # Carthage/Checkouts 55 | 56 | Carthage/Build 57 | 58 | # fastlane 59 | # 60 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 61 | # screenshots whenever they are needed. 62 | # For more information about the recommended setup visit: 63 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 64 | 65 | fastlane/report.xml 66 | fastlane/Preview.html 67 | fastlane/screenshots 68 | fastlane/test_output 69 | -------------------------------------------------------------------------------- /PartialOperatorApplicationTests/PartialOperatorApplicationTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PartialOperatorApplicationTests.swift 3 | // PartialOperatorApplicationTests 4 | // 5 | // Created by Michael Pangburn on 2/5/18. 6 | // Copyright © 2018 Michael Pangburn. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import PartialOperatorApplication 11 | 12 | class PartialOperatorApplicationTests: XCTestCase { 13 | 14 | class Reference: Equatable { 15 | static func == (lhs: Reference, rhs: Reference) -> Bool { 16 | return lhs === rhs 17 | } 18 | } 19 | 20 | func testPartialEquality() { 21 | let numbers = [1, 2, 3, 3, 3, 4, 5] 22 | XCTAssert(numbers.filter(==3) == [3, 3, 3]) 23 | XCTAssert(numbers.filter(3==) == [3, 3, 3]) 24 | XCTAssert(numbers.filter(!=3) == [1, 2, 4, 5]) 25 | XCTAssert(numbers.filter(~=3) == [3, 3, 3]) 26 | XCTAssert(numbers.filter(3~=) == [3, 3, 3]) 27 | } 28 | 29 | func testPartialIdentityEquality() { 30 | let (firstReference, secondReference) = (Reference(), Reference()) 31 | let dummies = [firstReference, firstReference, secondReference, secondReference] 32 | XCTAssert(dummies.filter(===firstReference) == [firstReference, firstReference]) 33 | XCTAssert(dummies.filter(firstReference===) == [firstReference, firstReference]) 34 | XCTAssert(dummies.filter(!==firstReference) == [secondReference, secondReference]) 35 | } 36 | 37 | func testPartialComparison() { 38 | let numbers = Array(1...10) 39 | XCTAssert(numbers.filter(>5) == Array(6...10)) 40 | XCTAssert(numbers.filter(5<=) == Array(5...10)) 41 | XCTAssert(numbers.filter(>=8) == Array(8...10)) 42 | XCTAssert(numbers.filter(8<) == Array(9...10)) 43 | XCTAssert(numbers.filter(<=3) == Array(1...3)) 44 | XCTAssert(numbers.filter(3>=) == Array(1...3)) 45 | } 46 | 47 | func testPartialNumericOperations() { 48 | let numbers = Array(1...10) 49 | XCTAssert(numbers.map(+2) == Array(3...12)) 50 | XCTAssert(numbers.map(2+) == Array(3...12)) 51 | XCTAssert(numbers.map(11-) == Array(1...10).reversed()) 52 | XCTAssert(numbers.map(*2) == Array(stride(from: 2, through: 20, by: 2))) 53 | XCTAssert(numbers.map(2*) == Array(stride(from: 2, through: 20, by: 2))) 54 | } 55 | 56 | func testPartialFloatingPointOperations() { 57 | let numbers = Array(stride(from: 1.0, through: 5.0, by: 1.0)) 58 | XCTAssert(numbers.map(/2) == Array(stride(from: 0.5, through: 2.5, by: 0.5))) 59 | XCTAssert(numbers.map(2/) == [2.0, 1.0, 2.0 / 3.0, 0.5, 0.4]) 60 | } 61 | 62 | func testPartialBinaryIntegerOperations() { 63 | let numbers = Array(1...5) 64 | XCTAssert(numbers.map(/2) == [0, 1, 1, 2, 2]) 65 | XCTAssert(numbers.map(%2) == [1, 0, 1, 0, 1]) 66 | let factorsOfTwelve = [1, 2, 3, 4, 6, 12] 67 | XCTAssert(factorsOfTwelve.map(12/) == Array(factorsOfTwelve).reversed()) 68 | XCTAssert(factorsOfTwelve.map(10%) == [0, 0, 1, 2, 4, 10]) 69 | } 70 | 71 | func testPartialBoolOperations() { 72 | let bools = [true, false, true, false] 73 | XCTAssert(bools.map(&&true) == bools) 74 | XCTAssert(bools.map(true&&) == bools) 75 | XCTAssert(bools.map(&&false) == Array(repeating: false, count: bools.count)) 76 | XCTAssert(bools.map(false&&) == Array(repeating: false, count: bools.count)) 77 | XCTAssert(bools.map(||true) == Array(repeating: true, count: bools.count)) 78 | XCTAssert(bools.map(true||) == Array(repeating: true, count: bools.count)) 79 | XCTAssert(bools.map(||false) == bools) 80 | XCTAssert(bools.map(false||) == bools) 81 | } 82 | 83 | func testPartialNilCoalescing() { 84 | let maybeNumbers: [Int?] = [1, 2, nil, 4, nil, 6] 85 | XCTAssert(maybeNumbers.map(??100) == [1, 2, 100, 4, 100, 6]) 86 | } 87 | 88 | func testPartialsInSwitch() { 89 | func signum(_ x: Int) -> Int { 90 | switch x { 91 | case not(>=0): 92 | return -1 93 | case ==0: 94 | return 0 95 | case >0: 96 | return 1 97 | default: 98 | fatalError() 99 | } 100 | } 101 | 102 | XCTAssert(signum(-5) == -1) 103 | XCTAssert(signum(0) == 0) 104 | XCTAssert(signum(3) == 1) 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Partially Applied Operators 2 | 3 | [![Swift 4.0](https://img.shields.io/badge/Swift-4.0-orange.svg?style=flat)](#) 4 | [![@pangburnout](https://img.shields.io/badge/contact-@pangburnout-blue.svg?style=flat)](https://twitter.com/pangburnout) 5 | 6 | A thought experiment in bringing the semantics of Haskell's partial application of operators to Swift. 7 | 8 | ## Background 9 | In functional programming languages, [currying](https://en.wikipedia.org/wiki/Currying) enables the partial application of functions. For example, consider a function `add` that takes two integer arguments and returns their sum. Currying allows a single argument to be passed to `add` to create a new function. This new function takes only a single integer argument and returns its sum with the first argument passed. When `add` is passed only a single argument, it is partially applied. 10 | 11 | In a language like Haskell, functions that take multiple arguments are inherently curried. For example, here is the signature of `add` in Haskell: 12 | 13 | ```haskell 14 | add :: Int -> Int -> Int 15 | ``` 16 | 17 | Notice how the return `->` separates not just the arguments from the return type, but also the arguments from one another. In Swift, we might think to write the signature of `add` like so: 18 | 19 | ```swift 20 | func add(_ x: Int, _ y: Int) -> Int 21 | ``` 22 | 23 | However, when defined in this manner, `add` is not curried. To make use of `add` as a curried function in Swift, we would write its signature in a different way: 24 | 25 | ```swift 26 | func add(_ x: Int) -> (_ y: Int) -> Int 27 | ``` 28 | 29 | This curried `add` would be used slightly differently from how we defined it initially: 30 | 31 | ```swift 32 | // Using definition 1: 33 | add(2, 4) // 6 34 | 35 | // Using definition 2: 36 | add(2)(4) // 6 37 | ``` 38 | 39 | While the extra pair of parentheses is unappealing, we gain powerful functionality through currying: 40 | 41 | ```swift 42 | let add2 = add(2) 43 | add2(4) // 6 44 | add2(10) // 12 45 | ``` 46 | 47 | In this way, currying allows for composable, reusable functions. 48 | 49 | Since operators are really just infix functions with special symbols, they can also be partially applied. Partially appplied operators are especially useful for mapping over or filtering a list: 50 | 51 | ```haskell 52 | numbers = [1, 2, 3, 4, 5] 53 | map (+2) numbers -- [3, 4, 5, 6, 7] 54 | filter (>=3) numbers -- [3, 4, 5] 55 | ``` 56 | 57 | In Swift, we can do something similar using trailing closure syntax: 58 | 59 | ```swift 60 | let numbers = [1, 2, 3, 4, 5] 61 | numbers.map { $0 + 2 } // [3, 4, 5, 6, 7] 62 | numbers.filter { $0 >= 3 } // [3, 4, 5] 63 | ``` 64 | 65 | However, there is a key difference here: in the Haskell example, we make use of operators without explicitly identifying their operands—this is called [point-free style](https://en.wikipedia.org/wiki/Tacit_programming). In Swift, we identify the operand in the map or filter with `$0`. 66 | 67 | The goal of this project is to bring the semantics of Haskell's partially applied operators to Swift: 68 | 69 | ```swift 70 | let numbers = [1, 2, 3, 4, 5] 71 | numbers.map(+2) // [3, 4, 5, 6, 7] 72 | numbers.filter(>=3) // [3, 4, 5] 73 | ``` 74 | 75 | ## Implementation 76 | The built-in operators defined in the Swift Standard Library are not curried. We could curry them using a [helper function](https://github.com/pointfreeco/swift-prelude/blob/b23463ebd7c1ce11600f86cbcb8165098fd44693/Sources/Prelude/Curry.swift), but calling `curry` whenever we partially apply an operator would be inelegant and obscure our intent. 77 | 78 | Instead, we define "unary" versions of the infix operators in order to partially apply them. For example, our `add` example from above becomes 79 | 80 | ```swift 81 | prefix func + (rhs: T) -> (_ lhs: T) -> T { 82 | return { $0 + rhs } 83 | } 84 | ``` 85 | 86 | Where possible, we define both prefix and postfix versions of operators: 87 | 88 | ```swift 89 | postfix func + (lhs: T) -> (_ rhs: T) -> T { 90 | return { lhs + $0 } 91 | } 92 | ``` 93 | 94 | Defining both versions is most important for operations that are not commutative, such as division. 95 | 96 | ## Limitations 97 | Some limitations are imposed on operator declarations in certain contexts: 98 | 99 | - The less-than symbol `<` cannot be used as a prefix operator, and the greater-than symbol `>` cannot be used as a postfix operator. These symbols are reserved in these contexts to avoid compiler confusion in identifying generics. 100 | - An overloaded prefix `-` on Numeric types is not properly interpreted by the compiler. Interestingly, `+` does not have this problem despite also being already defined as a prefix operator on Numeric types. 101 | - Prefix `&` is reserved for passing variables as inout parameters, so it cannot be used as a prefix in partially applying the bitwise AND operator.__*__ 102 | - Postfix operators cannot begin with '!' because of its use with Optionals, which prevents the postfix definitions of `!=` and `!==`.__*__ 103 | - Postfix operators cannot begin with '?' because of its use with Optionals, which prevents the postfix definition of `??`. 104 | 105 | __*__ In practice, the restrictions on these operators are trivial since their operations are commutative, and either their prefix or postfix version can be implemented without issues. 106 | 107 | ## Looking Forward 108 | While [SE-002](https://github.com/apple/swift-evolution/blob/master/proposals/0002-remove-currying.md) removed previous syntax for currying, it also included some brief thoughts on [the future of currying in Swift](https://github.com/apple/swift-evolution/blob/master/proposals/0002-remove-currying.md#alternatives-considered). While we have yet to see movement on this front, inherently curried functions would have significant implications for the functional Swift community. Hopefully, the syntax introduced through this project will one day be native to Swift through built-in partial function application. -------------------------------------------------------------------------------- /Sources/PartialOperatorApplication.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PartialOperatorApplication.swift 3 | // PartialOperatorApplication 4 | // 5 | // Created by Michael Pangburn on 2/5/18. 6 | // Copyright © 2018 Michael Pangburn. All rights reserved. 7 | // 8 | 9 | // MARK: - Equatable operators 10 | 11 | prefix operator == 12 | prefix func == (rhs: T) -> (_ lhs: T) -> Bool { 13 | return { $0 == rhs } 14 | } 15 | 16 | postfix operator == 17 | postfix func == (lhs: T) -> (_ rhs: T) -> Bool { 18 | return { lhs == $0 } 19 | } 20 | 21 | prefix operator != 22 | prefix func != (rhs: T) -> (_ lhs: T) -> Bool { 23 | return { $0 != rhs } 24 | } 25 | 26 | /* Postfix operators cannot begin with '!' because of its use with Optionals */ 27 | // postfix operator != 28 | // postfix func != (lhs: T) -> (_ rhs: T) -> Bool { 29 | // return { lhs != $0 } 30 | // } 31 | 32 | prefix operator ~= 33 | prefix func ~= (rhs: T) -> (_ lhs: T) -> Bool { 34 | return { $0 ~= rhs } 35 | } 36 | 37 | postfix operator ~= 38 | postfix func ~= (lhs: T) -> (_ rhs: T) -> Bool { 39 | return { lhs ~= $0 } 40 | } 41 | 42 | // MARK: - Identity equatable operators 43 | 44 | prefix operator === 45 | prefix func === (rhs: T) -> (_ lhs: T) -> Bool { 46 | return { $0 === rhs } 47 | } 48 | 49 | postfix operator === 50 | postfix func === (lhs: T) -> (_ rhs: T) -> Bool { 51 | return { lhs === $0 } 52 | } 53 | 54 | prefix operator !== 55 | prefix func !== (rhs: T) -> (_ lhs: T) -> Bool { 56 | return { $0 !== rhs } 57 | } 58 | 59 | /* Postfix operators cannot begin with '!' because of its use with Optionals */ 60 | // postfix operator !== 61 | // postfix func !== (lhs: T) -> (_ rhs: T) -> Bool { 62 | // return { lhs !== $0 } 63 | // } 64 | 65 | // MARK: - Comparable operators 66 | 67 | /* Prefix '<' is reserved to avoid compiler confusion in identifying generics */ 68 | // prefix operator < 69 | // prefix func < (rhs: T) -> (_ lhs: T) -> Bool { 70 | // return { $0 < rhs } 71 | // } 72 | 73 | postfix operator < 74 | postfix func < (lhs: T) -> (_ rhs: T) -> Bool { 75 | return { lhs < $0 } 76 | } 77 | 78 | prefix operator > 79 | prefix func > (rhs: T) -> (_ lhs: T) -> Bool { 80 | return { $0 > rhs } 81 | } 82 | 83 | /* Postfix '>' is reserved to avoid compiler confusion in identifying generics */ 84 | // postfix operator > 85 | // postfix func > (lhs: T) -> (_ rhs: T) -> Bool { 86 | // return { lhs > $0 } 87 | // } 88 | 89 | prefix operator <= 90 | prefix func <= (rhs: T) -> (_ lhs: T) -> Bool { 91 | return { $0 <= rhs } 92 | } 93 | 94 | postfix operator <= 95 | postfix func <= (lhs: T) -> (_ rhs: T) -> Bool { 96 | return { lhs <= $0 } 97 | } 98 | 99 | prefix operator >= 100 | prefix func >= (rhs: T) -> (_ lhs: T) -> Bool { 101 | return { $0 >= rhs } 102 | } 103 | 104 | postfix operator >= 105 | postfix func >= (lhs: T) -> (_ rhs: T) -> Bool { 106 | return { lhs >= $0 } 107 | } 108 | 109 | // MARK: - Numeric operators 110 | 111 | prefix func + (rhs: T) -> (_ lhs: T) -> T { 112 | return { $0 + rhs } 113 | } 114 | 115 | postfix operator + 116 | postfix func + (lhs: T) -> (_ rhs: T) -> T { 117 | return { lhs + $0 } 118 | } 119 | 120 | /* Interestingly, overloading unary '+' works fine, but not unary '-' */ 121 | // prefix func - (rhs: T) -> (_ lhs: T) -> T { 122 | // return { $0 - rhs } 123 | // } 124 | 125 | postfix operator - 126 | postfix func - (lhs: T) -> (_ rhs: T) -> T { 127 | return { lhs - $0 } 128 | } 129 | 130 | prefix operator * 131 | prefix func * (rhs: T) -> (_ lhs: T) -> T { 132 | return { $0 * rhs } 133 | } 134 | 135 | postfix operator * 136 | postfix func * (lhs: T) -> (_ rhs: T) -> T { 137 | return { lhs * $0 } 138 | } 139 | 140 | // MARK: - FloatingPoint operators 141 | 142 | prefix operator / 143 | prefix func / (rhs: T) -> (_ lhs: T) -> T { 144 | return { $0 / rhs } 145 | } 146 | 147 | postfix operator / 148 | postfix func / (lhs: T) -> (_ rhs: T) -> T { 149 | return { lhs / $0 } 150 | } 151 | 152 | // MARK: - BinaryInteger operators 153 | 154 | prefix func / (rhs: T) -> (_ lhs: T) -> T { 155 | return { $0 / rhs } 156 | } 157 | 158 | postfix func / (lhs: T) -> (_ rhs: T) -> T { 159 | return { lhs / $0 } 160 | } 161 | 162 | prefix operator % 163 | prefix func % (rhs: T) -> (_ lhs: T) -> T { 164 | return { $0 % rhs } 165 | } 166 | 167 | postfix operator % 168 | postfix func % (lhs: T) -> (_ rhs: T) -> T { 169 | return { lhs % $0 } 170 | } 171 | 172 | /* Prefix '&' is reserved for passing variables as inout parameters */ 173 | // prefix operator & 174 | // prefix func & (rhs: T) -> (_ lhs: T) -> T { 175 | // return { $0 & rhs } 176 | // } 177 | 178 | postfix operator & 179 | postfix func & (lhs: T) -> (_ rhs: T) -> T { 180 | return { lhs & $0 } 181 | } 182 | 183 | prefix operator | 184 | prefix func | (rhs: T) -> (_ lhs: T) -> T { 185 | return { $0 | rhs } 186 | } 187 | 188 | postfix operator | 189 | postfix func | (lhs: T) -> (_ rhs: T) -> T { 190 | return { lhs | $0 } 191 | } 192 | 193 | prefix operator ^ 194 | prefix func ^ (rhs: T) -> (_ lhs: T) -> T { 195 | return { $0 ^ rhs } 196 | } 197 | 198 | postfix operator ^ 199 | postfix func ^ (lhs: T) -> (_ rhs: T) -> T { 200 | return { lhs ^ $0 } 201 | } 202 | 203 | prefix operator << 204 | prefix func << (rhs: T) -> (_ lhs: T) -> T { 205 | return { $0 << rhs } 206 | } 207 | 208 | postfix operator << 209 | postfix func << (lhs: T) -> (_ rhs: T) -> T { 210 | return { lhs << $0 } 211 | } 212 | 213 | prefix operator >> 214 | prefix func >> (rhs: T) -> (_ lhs: T) -> T { 215 | return { $0 >> rhs } 216 | } 217 | 218 | postfix operator >> 219 | postfix func >> (lhs: T) -> (_ rhs: T) -> T { 220 | return { lhs >> $0 } 221 | } 222 | 223 | // MARK: - FixedWidthInteger operators 224 | 225 | prefix operator &+ 226 | prefix func &+ (rhs: T) -> (_ lhs: T) -> T { 227 | return { $0 &+ rhs } 228 | } 229 | 230 | postfix operator &+ 231 | postfix func &+ (lhs: T) -> (_ rhs: T) -> T { 232 | return { lhs &+ $0 } 233 | } 234 | 235 | prefix operator &- 236 | prefix func &- (rhs: T) -> (_ lhs: T) -> T { 237 | return { $0 &- rhs } 238 | } 239 | 240 | postfix operator &- 241 | postfix func &- (lhs: T) -> (_ rhs: T) -> T { 242 | return { lhs &- $0 } 243 | } 244 | 245 | prefix operator &* 246 | prefix func &* (rhs: T) -> (_ lhs: T) -> T { 247 | return { $0 &* rhs } 248 | } 249 | 250 | postfix operator &* 251 | postfix func &* (lhs: T) -> (_ rhs: T) -> T { 252 | return { lhs &* $0 } 253 | } 254 | 255 | prefix operator &<< 256 | prefix func &<< (rhs: T) -> (_ lhs: T) -> T { 257 | return { $0 &<< rhs } 258 | } 259 | 260 | postfix operator &<< 261 | postfix func &<< (lhs: T) -> (_ rhs: T) -> T { 262 | return { lhs &<< $0 } 263 | } 264 | 265 | prefix operator &>> 266 | prefix func &>> (rhs: T) -> (_ lhs: T) -> T { 267 | return { $0 &>> rhs } 268 | } 269 | 270 | postfix operator &>> 271 | postfix func &>> (lhs: T) -> (_ rhs: T) -> T { 272 | return { lhs &>> $0 } 273 | } 274 | 275 | // MARK: - Bool operators 276 | 277 | prefix operator && 278 | prefix func && (rhs: @escaping @autoclosure () -> Bool) -> (_ lhs: Bool) -> Bool { 279 | return { $0 && rhs() } 280 | } 281 | 282 | postfix operator && 283 | postfix func && (lhs: Bool) -> (_ rhs: Bool) -> Bool { 284 | return { lhs && $0 } 285 | } 286 | 287 | prefix operator || 288 | prefix func || (rhs: @escaping @autoclosure () -> Bool) -> (_ lhs: Bool) -> Bool { 289 | return { $0 || rhs() } 290 | } 291 | 292 | postfix operator || 293 | postfix func || (lhs: Bool) -> (_ rhs: Bool) -> Bool { 294 | return { lhs || $0 } 295 | } 296 | 297 | // MARK: - Optional operators 298 | 299 | prefix operator ?? 300 | prefix func ?? (rhs: @escaping @autoclosure () -> T) -> (_ lhs: T?) -> T { 301 | return { $0 ?? rhs() } 302 | } 303 | 304 | /* Postfix operators cannot begin with '?' because of its use with Optionals */ 305 | // postfix operator ?? 306 | // postfix func ?? (lhs: T?) -> (_ rhs: T) -> T { 307 | // return { lhs ?? $0 } 308 | // } 309 | 310 | // MARK: - Utilities 311 | 312 | func not(_ f: @escaping (T) -> Bool) -> (T) -> Bool { 313 | return { !f($0) } 314 | } 315 | 316 | prefix func ! (f: @escaping (T) -> Bool) -> (T) -> Bool { 317 | return { !f($0) } 318 | } 319 | 320 | // c.f. https://oleb.net/blog/2015/09/swift-pattern-matching/ 321 | func ~= (pattern: (T) -> Bool, value: T) -> Bool { 322 | return pattern(value) 323 | } 324 | 325 | -------------------------------------------------------------------------------- /PartialOperatorApplication.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 89172A69202985FB00827A8D /* PartialOperatorApplication.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 89172A5F202985FB00827A8D /* PartialOperatorApplication.framework */; }; 11 | 89172A6E202985FB00827A8D /* PartialOperatorApplicationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89172A6D202985FB00827A8D /* PartialOperatorApplicationTests.swift */; }; 12 | 89172A70202985FB00827A8D /* PartialOperatorApplication.h in Headers */ = {isa = PBXBuildFile; fileRef = 89172A62202985FB00827A8D /* PartialOperatorApplication.h */; settings = {ATTRIBUTES = (Public, ); }; }; 13 | 89172A7B2029861200827A8D /* PartialOperatorApplication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89172A7A2029861200827A8D /* PartialOperatorApplication.swift */; }; 14 | /* End PBXBuildFile section */ 15 | 16 | /* Begin PBXContainerItemProxy section */ 17 | 89172A6A202985FB00827A8D /* PBXContainerItemProxy */ = { 18 | isa = PBXContainerItemProxy; 19 | containerPortal = 89172A56202985FB00827A8D /* Project object */; 20 | proxyType = 1; 21 | remoteGlobalIDString = 89172A5E202985FB00827A8D; 22 | remoteInfo = PartialOperatorApplication; 23 | }; 24 | /* End PBXContainerItemProxy section */ 25 | 26 | /* Begin PBXFileReference section */ 27 | 89172A5F202985FB00827A8D /* PartialOperatorApplication.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PartialOperatorApplication.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 28 | 89172A62202985FB00827A8D /* PartialOperatorApplication.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PartialOperatorApplication.h; sourceTree = ""; }; 29 | 89172A63202985FB00827A8D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 30 | 89172A68202985FB00827A8D /* PartialOperatorApplicationTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PartialOperatorApplicationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 31 | 89172A6D202985FB00827A8D /* PartialOperatorApplicationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PartialOperatorApplicationTests.swift; sourceTree = ""; }; 32 | 89172A6F202985FB00827A8D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 33 | 89172A7A2029861200827A8D /* PartialOperatorApplication.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PartialOperatorApplication.swift; sourceTree = ""; }; 34 | /* End PBXFileReference section */ 35 | 36 | /* Begin PBXFrameworksBuildPhase section */ 37 | 89172A5B202985FB00827A8D /* Frameworks */ = { 38 | isa = PBXFrameworksBuildPhase; 39 | buildActionMask = 2147483647; 40 | files = ( 41 | ); 42 | runOnlyForDeploymentPostprocessing = 0; 43 | }; 44 | 89172A65202985FB00827A8D /* Frameworks */ = { 45 | isa = PBXFrameworksBuildPhase; 46 | buildActionMask = 2147483647; 47 | files = ( 48 | 89172A69202985FB00827A8D /* PartialOperatorApplication.framework in Frameworks */, 49 | ); 50 | runOnlyForDeploymentPostprocessing = 0; 51 | }; 52 | /* End PBXFrameworksBuildPhase section */ 53 | 54 | /* Begin PBXGroup section */ 55 | 89172A55202985FB00827A8D = { 56 | isa = PBXGroup; 57 | children = ( 58 | 89172A792029860900827A8D /* Sources */, 59 | 89172A61202985FB00827A8D /* PartialOperatorApplication */, 60 | 89172A6C202985FB00827A8D /* PartialOperatorApplicationTests */, 61 | 89172A60202985FB00827A8D /* Products */, 62 | ); 63 | sourceTree = ""; 64 | }; 65 | 89172A60202985FB00827A8D /* Products */ = { 66 | isa = PBXGroup; 67 | children = ( 68 | 89172A5F202985FB00827A8D /* PartialOperatorApplication.framework */, 69 | 89172A68202985FB00827A8D /* PartialOperatorApplicationTests.xctest */, 70 | ); 71 | name = Products; 72 | sourceTree = ""; 73 | }; 74 | 89172A61202985FB00827A8D /* PartialOperatorApplication */ = { 75 | isa = PBXGroup; 76 | children = ( 77 | 89172A62202985FB00827A8D /* PartialOperatorApplication.h */, 78 | 89172A63202985FB00827A8D /* Info.plist */, 79 | ); 80 | path = PartialOperatorApplication; 81 | sourceTree = ""; 82 | }; 83 | 89172A6C202985FB00827A8D /* PartialOperatorApplicationTests */ = { 84 | isa = PBXGroup; 85 | children = ( 86 | 89172A6D202985FB00827A8D /* PartialOperatorApplicationTests.swift */, 87 | 89172A6F202985FB00827A8D /* Info.plist */, 88 | ); 89 | path = PartialOperatorApplicationTests; 90 | sourceTree = ""; 91 | }; 92 | 89172A792029860900827A8D /* Sources */ = { 93 | isa = PBXGroup; 94 | children = ( 95 | 89172A7A2029861200827A8D /* PartialOperatorApplication.swift */, 96 | ); 97 | path = Sources; 98 | sourceTree = ""; 99 | }; 100 | /* End PBXGroup section */ 101 | 102 | /* Begin PBXHeadersBuildPhase section */ 103 | 89172A5C202985FB00827A8D /* Headers */ = { 104 | isa = PBXHeadersBuildPhase; 105 | buildActionMask = 2147483647; 106 | files = ( 107 | 89172A70202985FB00827A8D /* PartialOperatorApplication.h in Headers */, 108 | ); 109 | runOnlyForDeploymentPostprocessing = 0; 110 | }; 111 | /* End PBXHeadersBuildPhase section */ 112 | 113 | /* Begin PBXNativeTarget section */ 114 | 89172A5E202985FB00827A8D /* PartialOperatorApplication */ = { 115 | isa = PBXNativeTarget; 116 | buildConfigurationList = 89172A73202985FB00827A8D /* Build configuration list for PBXNativeTarget "PartialOperatorApplication" */; 117 | buildPhases = ( 118 | 89172A5A202985FB00827A8D /* Sources */, 119 | 89172A5B202985FB00827A8D /* Frameworks */, 120 | 89172A5C202985FB00827A8D /* Headers */, 121 | 89172A5D202985FB00827A8D /* Resources */, 122 | ); 123 | buildRules = ( 124 | ); 125 | dependencies = ( 126 | ); 127 | name = PartialOperatorApplication; 128 | productName = PartialOperatorApplication; 129 | productReference = 89172A5F202985FB00827A8D /* PartialOperatorApplication.framework */; 130 | productType = "com.apple.product-type.framework"; 131 | }; 132 | 89172A67202985FB00827A8D /* PartialOperatorApplicationTests */ = { 133 | isa = PBXNativeTarget; 134 | buildConfigurationList = 89172A76202985FB00827A8D /* Build configuration list for PBXNativeTarget "PartialOperatorApplicationTests" */; 135 | buildPhases = ( 136 | 89172A64202985FB00827A8D /* Sources */, 137 | 89172A65202985FB00827A8D /* Frameworks */, 138 | 89172A66202985FB00827A8D /* Resources */, 139 | ); 140 | buildRules = ( 141 | ); 142 | dependencies = ( 143 | 89172A6B202985FB00827A8D /* PBXTargetDependency */, 144 | ); 145 | name = PartialOperatorApplicationTests; 146 | productName = PartialOperatorApplicationTests; 147 | productReference = 89172A68202985FB00827A8D /* PartialOperatorApplicationTests.xctest */; 148 | productType = "com.apple.product-type.bundle.unit-test"; 149 | }; 150 | /* End PBXNativeTarget section */ 151 | 152 | /* Begin PBXProject section */ 153 | 89172A56202985FB00827A8D /* Project object */ = { 154 | isa = PBXProject; 155 | attributes = { 156 | LastSwiftUpdateCheck = 0920; 157 | LastUpgradeCheck = 0920; 158 | ORGANIZATIONNAME = "Michael Pangburn"; 159 | TargetAttributes = { 160 | 89172A5E202985FB00827A8D = { 161 | CreatedOnToolsVersion = 9.2; 162 | LastSwiftMigration = 0920; 163 | ProvisioningStyle = Automatic; 164 | }; 165 | 89172A67202985FB00827A8D = { 166 | CreatedOnToolsVersion = 9.2; 167 | ProvisioningStyle = Automatic; 168 | }; 169 | }; 170 | }; 171 | buildConfigurationList = 89172A59202985FB00827A8D /* Build configuration list for PBXProject "PartialOperatorApplication" */; 172 | compatibilityVersion = "Xcode 8.0"; 173 | developmentRegion = en; 174 | hasScannedForEncodings = 0; 175 | knownRegions = ( 176 | en, 177 | ); 178 | mainGroup = 89172A55202985FB00827A8D; 179 | productRefGroup = 89172A60202985FB00827A8D /* Products */; 180 | projectDirPath = ""; 181 | projectRoot = ""; 182 | targets = ( 183 | 89172A5E202985FB00827A8D /* PartialOperatorApplication */, 184 | 89172A67202985FB00827A8D /* PartialOperatorApplicationTests */, 185 | ); 186 | }; 187 | /* End PBXProject section */ 188 | 189 | /* Begin PBXResourcesBuildPhase section */ 190 | 89172A5D202985FB00827A8D /* Resources */ = { 191 | isa = PBXResourcesBuildPhase; 192 | buildActionMask = 2147483647; 193 | files = ( 194 | ); 195 | runOnlyForDeploymentPostprocessing = 0; 196 | }; 197 | 89172A66202985FB00827A8D /* Resources */ = { 198 | isa = PBXResourcesBuildPhase; 199 | buildActionMask = 2147483647; 200 | files = ( 201 | ); 202 | runOnlyForDeploymentPostprocessing = 0; 203 | }; 204 | /* End PBXResourcesBuildPhase section */ 205 | 206 | /* Begin PBXSourcesBuildPhase section */ 207 | 89172A5A202985FB00827A8D /* Sources */ = { 208 | isa = PBXSourcesBuildPhase; 209 | buildActionMask = 2147483647; 210 | files = ( 211 | 89172A7B2029861200827A8D /* PartialOperatorApplication.swift in Sources */, 212 | ); 213 | runOnlyForDeploymentPostprocessing = 0; 214 | }; 215 | 89172A64202985FB00827A8D /* Sources */ = { 216 | isa = PBXSourcesBuildPhase; 217 | buildActionMask = 2147483647; 218 | files = ( 219 | 89172A6E202985FB00827A8D /* PartialOperatorApplicationTests.swift in Sources */, 220 | ); 221 | runOnlyForDeploymentPostprocessing = 0; 222 | }; 223 | /* End PBXSourcesBuildPhase section */ 224 | 225 | /* Begin PBXTargetDependency section */ 226 | 89172A6B202985FB00827A8D /* PBXTargetDependency */ = { 227 | isa = PBXTargetDependency; 228 | target = 89172A5E202985FB00827A8D /* PartialOperatorApplication */; 229 | targetProxy = 89172A6A202985FB00827A8D /* PBXContainerItemProxy */; 230 | }; 231 | /* End PBXTargetDependency section */ 232 | 233 | /* Begin XCBuildConfiguration section */ 234 | 89172A71202985FB00827A8D /* Debug */ = { 235 | isa = XCBuildConfiguration; 236 | buildSettings = { 237 | ALWAYS_SEARCH_USER_PATHS = NO; 238 | CLANG_ANALYZER_NONNULL = YES; 239 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 240 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 241 | CLANG_CXX_LIBRARY = "libc++"; 242 | CLANG_ENABLE_MODULES = YES; 243 | CLANG_ENABLE_OBJC_ARC = YES; 244 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 245 | CLANG_WARN_BOOL_CONVERSION = YES; 246 | CLANG_WARN_COMMA = YES; 247 | CLANG_WARN_CONSTANT_CONVERSION = YES; 248 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 249 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 250 | CLANG_WARN_EMPTY_BODY = YES; 251 | CLANG_WARN_ENUM_CONVERSION = YES; 252 | CLANG_WARN_INFINITE_RECURSION = YES; 253 | CLANG_WARN_INT_CONVERSION = YES; 254 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 255 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 256 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 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 = 11.2; 284 | MTL_ENABLE_DEBUG_INFO = YES; 285 | ONLY_ACTIVE_ARCH = YES; 286 | SDKROOT = iphoneos; 287 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 288 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 289 | VERSIONING_SYSTEM = "apple-generic"; 290 | VERSION_INFO_PREFIX = ""; 291 | }; 292 | name = Debug; 293 | }; 294 | 89172A72202985FB00827A8D /* Release */ = { 295 | isa = XCBuildConfiguration; 296 | buildSettings = { 297 | ALWAYS_SEARCH_USER_PATHS = NO; 298 | CLANG_ANALYZER_NONNULL = YES; 299 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 300 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 301 | CLANG_CXX_LIBRARY = "libc++"; 302 | CLANG_ENABLE_MODULES = YES; 303 | CLANG_ENABLE_OBJC_ARC = YES; 304 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 305 | CLANG_WARN_BOOL_CONVERSION = YES; 306 | CLANG_WARN_COMMA = YES; 307 | CLANG_WARN_CONSTANT_CONVERSION = YES; 308 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 309 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 310 | CLANG_WARN_EMPTY_BODY = YES; 311 | CLANG_WARN_ENUM_CONVERSION = YES; 312 | CLANG_WARN_INFINITE_RECURSION = YES; 313 | CLANG_WARN_INT_CONVERSION = YES; 314 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 315 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 316 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 317 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 318 | CLANG_WARN_STRICT_PROTOTYPES = YES; 319 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 320 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 321 | CLANG_WARN_UNREACHABLE_CODE = YES; 322 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 323 | CODE_SIGN_IDENTITY = "iPhone Developer"; 324 | COPY_PHASE_STRIP = NO; 325 | CURRENT_PROJECT_VERSION = 1; 326 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 327 | ENABLE_NS_ASSERTIONS = NO; 328 | ENABLE_STRICT_OBJC_MSGSEND = YES; 329 | GCC_C_LANGUAGE_STANDARD = gnu11; 330 | GCC_NO_COMMON_BLOCKS = YES; 331 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 332 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 333 | GCC_WARN_UNDECLARED_SELECTOR = YES; 334 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 335 | GCC_WARN_UNUSED_FUNCTION = YES; 336 | GCC_WARN_UNUSED_VARIABLE = YES; 337 | IPHONEOS_DEPLOYMENT_TARGET = 11.2; 338 | MTL_ENABLE_DEBUG_INFO = NO; 339 | SDKROOT = iphoneos; 340 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 341 | VALIDATE_PRODUCT = YES; 342 | VERSIONING_SYSTEM = "apple-generic"; 343 | VERSION_INFO_PREFIX = ""; 344 | }; 345 | name = Release; 346 | }; 347 | 89172A74202985FB00827A8D /* Debug */ = { 348 | isa = XCBuildConfiguration; 349 | buildSettings = { 350 | CLANG_ENABLE_MODULES = YES; 351 | CODE_SIGN_IDENTITY = ""; 352 | CODE_SIGN_STYLE = Automatic; 353 | DEFINES_MODULE = YES; 354 | DEVELOPMENT_TEAM = 5Q5Q8W9ATZ; 355 | DYLIB_COMPATIBILITY_VERSION = 1; 356 | DYLIB_CURRENT_VERSION = 1; 357 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 358 | INFOPLIST_FILE = PartialOperatorApplication/Info.plist; 359 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 360 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 361 | PRODUCT_BUNDLE_IDENTIFIER = com.mpangburn.PartialOperatorApplication; 362 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 363 | SKIP_INSTALL = YES; 364 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 365 | SWIFT_VERSION = 4.0; 366 | TARGETED_DEVICE_FAMILY = "1,2"; 367 | }; 368 | name = Debug; 369 | }; 370 | 89172A75202985FB00827A8D /* Release */ = { 371 | isa = XCBuildConfiguration; 372 | buildSettings = { 373 | CLANG_ENABLE_MODULES = YES; 374 | CODE_SIGN_IDENTITY = ""; 375 | CODE_SIGN_STYLE = Automatic; 376 | DEFINES_MODULE = YES; 377 | DEVELOPMENT_TEAM = 5Q5Q8W9ATZ; 378 | DYLIB_COMPATIBILITY_VERSION = 1; 379 | DYLIB_CURRENT_VERSION = 1; 380 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 381 | INFOPLIST_FILE = PartialOperatorApplication/Info.plist; 382 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 383 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 384 | PRODUCT_BUNDLE_IDENTIFIER = com.mpangburn.PartialOperatorApplication; 385 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 386 | SKIP_INSTALL = YES; 387 | SWIFT_VERSION = 4.0; 388 | TARGETED_DEVICE_FAMILY = "1,2"; 389 | }; 390 | name = Release; 391 | }; 392 | 89172A77202985FB00827A8D /* Debug */ = { 393 | isa = XCBuildConfiguration; 394 | buildSettings = { 395 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 396 | CODE_SIGN_STYLE = Automatic; 397 | DEVELOPMENT_TEAM = 5Q5Q8W9ATZ; 398 | INFOPLIST_FILE = PartialOperatorApplicationTests/Info.plist; 399 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 400 | PRODUCT_BUNDLE_IDENTIFIER = com.mpangburn.PartialOperatorApplicationTests; 401 | PRODUCT_NAME = "$(TARGET_NAME)"; 402 | SWIFT_VERSION = 4.0; 403 | TARGETED_DEVICE_FAMILY = "1,2"; 404 | }; 405 | name = Debug; 406 | }; 407 | 89172A78202985FB00827A8D /* Release */ = { 408 | isa = XCBuildConfiguration; 409 | buildSettings = { 410 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 411 | CODE_SIGN_STYLE = Automatic; 412 | DEVELOPMENT_TEAM = 5Q5Q8W9ATZ; 413 | INFOPLIST_FILE = PartialOperatorApplicationTests/Info.plist; 414 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 415 | PRODUCT_BUNDLE_IDENTIFIER = com.mpangburn.PartialOperatorApplicationTests; 416 | PRODUCT_NAME = "$(TARGET_NAME)"; 417 | SWIFT_VERSION = 4.0; 418 | TARGETED_DEVICE_FAMILY = "1,2"; 419 | }; 420 | name = Release; 421 | }; 422 | /* End XCBuildConfiguration section */ 423 | 424 | /* Begin XCConfigurationList section */ 425 | 89172A59202985FB00827A8D /* Build configuration list for PBXProject "PartialOperatorApplication" */ = { 426 | isa = XCConfigurationList; 427 | buildConfigurations = ( 428 | 89172A71202985FB00827A8D /* Debug */, 429 | 89172A72202985FB00827A8D /* Release */, 430 | ); 431 | defaultConfigurationIsVisible = 0; 432 | defaultConfigurationName = Release; 433 | }; 434 | 89172A73202985FB00827A8D /* Build configuration list for PBXNativeTarget "PartialOperatorApplication" */ = { 435 | isa = XCConfigurationList; 436 | buildConfigurations = ( 437 | 89172A74202985FB00827A8D /* Debug */, 438 | 89172A75202985FB00827A8D /* Release */, 439 | ); 440 | defaultConfigurationIsVisible = 0; 441 | defaultConfigurationName = Release; 442 | }; 443 | 89172A76202985FB00827A8D /* Build configuration list for PBXNativeTarget "PartialOperatorApplicationTests" */ = { 444 | isa = XCConfigurationList; 445 | buildConfigurations = ( 446 | 89172A77202985FB00827A8D /* Debug */, 447 | 89172A78202985FB00827A8D /* Release */, 448 | ); 449 | defaultConfigurationIsVisible = 0; 450 | defaultConfigurationName = Release; 451 | }; 452 | /* End XCConfigurationList section */ 453 | }; 454 | rootObject = 89172A56202985FB00827A8D /* Project object */; 455 | } 456 | --------------------------------------------------------------------------------