├── .gitignore ├── .swift-version ├── .travis.yml ├── CHANGELOG.md ├── Comprehension.podspec ├── Comprehension.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcshareddata │ └── xcschemes │ └── Comprehension.xcscheme ├── LICENSE.md ├── Makefile ├── Package.swift ├── README.md ├── Resources ├── Info.plist └── xcconfigs │ ├── LICENSE │ ├── UniversalFramework_Base.xcconfig │ ├── UniversalFramework_Framework.xcconfig │ └── UniversalFramework_Test.xcconfig ├── Sources └── Comprehension │ └── Comprehension.swift └── Tests ├── ComprehensionTests └── ComprehensionTests.swift └── LinuxMain.swift /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | 5 | *.pbxuser 6 | !default.pbxuser 7 | *.mode1v3 8 | !default.mode1v3 9 | *.mode2v3 10 | !default.mode2v3 11 | *.perspectivev3 12 | !default.perspectivev3 13 | xcuserdata 14 | *.xccheckout 15 | *.moved-aside 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | *.xcscmblueprint 20 | 21 | Carthage/Build 22 | 23 | *.swp 24 | *.swo 25 | *~ 26 | -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 4.2 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | matrix: 2 | include: 3 | - env: ACTION=iOS 4 | - env: ACTION=macOS 5 | - env: ACTION=tvOS 6 | - env: ACTION=carthage 7 | - env: ACTION=swiftpm-macOS 8 | - env: ACTION=swiftpm-linux 9 | os: linux 10 | sudo: required 11 | dist: trusty 12 | language: generic 13 | 14 | os: osx 15 | language: objective-c 16 | osx_image: xcode10 17 | 18 | script: 19 | - make install-$ACTION && make test-$ACTION 20 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # master 2 | 3 | ## Breaking 4 | 5 | - None 6 | 7 | ## Enhancements 8 | 9 | - None 10 | -------------------------------------------------------------------------------- /Comprehension.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |spec| 2 | spec.name = 'Comprehension' 3 | spec.version = '0.0.3' 4 | spec.license = { :type => 'MIT' } 5 | spec.homepage = 'https://github.com/dduan/comprehension' 6 | spec.authors = { 'Daniel Duan' => 'daniel@duan.ca' } 7 | spec.summary = 'Provide list comprehension in Swift.' 8 | spec.source = { :git => 'https://github.com/dduan/comprehension.git', :tag => spec.version.to_s } 9 | spec.ios.deployment_target = "8.0" 10 | spec.osx.deployment_target = "10.10" 11 | spec.tvos.deployment_target = "9.0" 12 | spec.watchos.deployment_target = "2.0" 13 | spec.source_files = 'Sources/**/*.swift' 14 | spec.module_name = 'Comprehension' 15 | end 16 | -------------------------------------------------------------------------------- /Comprehension.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 3789D1691FDE196100D7335E /* Comprehension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3789D1681FDE196100D7335E /* Comprehension.swift */; }; 11 | 3789D16B1FDE197700D7335E /* ComprehensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3789D16A1FDE197700D7335E /* ComprehensionTests.swift */; }; 12 | C201748E1BD5509D00E4FE18 /* Comprehension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C20174831BD5509D00E4FE18 /* Comprehension.framework */; }; 13 | /* End PBXBuildFile section */ 14 | 15 | /* Begin PBXContainerItemProxy section */ 16 | C201748F1BD5509D00E4FE18 /* PBXContainerItemProxy */ = { 17 | isa = PBXContainerItemProxy; 18 | containerPortal = C201747A1BD5509D00E4FE18 /* Project object */; 19 | proxyType = 1; 20 | remoteGlobalIDString = C20174821BD5509D00E4FE18; 21 | remoteInfo = Comprehension; 22 | }; 23 | /* End PBXContainerItemProxy section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | 3789D1681FDE196100D7335E /* Comprehension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Comprehension.swift; path = Sources/Comprehension/Comprehension.swift; sourceTree = SOURCE_ROOT; }; 27 | 3789D16A1FDE197700D7335E /* ComprehensionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ComprehensionTests.swift; sourceTree = ""; }; 28 | C20174831BD5509D00E4FE18 /* Comprehension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Comprehension.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 29 | C201748D1BD5509D00E4FE18 /* ComprehensionTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ComprehensionTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 30 | C2C036D11C2B180D003FB853 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 31 | C2C036D41C2B180D003FB853 /* UniversalFramework_Base.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = UniversalFramework_Base.xcconfig; sourceTree = ""; }; 32 | C2C036D51C2B180D003FB853 /* UniversalFramework_Framework.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = UniversalFramework_Framework.xcconfig; sourceTree = ""; }; 33 | C2C036D61C2B180D003FB853 /* UniversalFramework_Test.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = UniversalFramework_Test.xcconfig; sourceTree = ""; }; 34 | /* End PBXFileReference section */ 35 | 36 | /* Begin PBXFrameworksBuildPhase section */ 37 | C201748A1BD5509D00E4FE18 /* Frameworks */ = { 38 | isa = PBXFrameworksBuildPhase; 39 | buildActionMask = 2147483647; 40 | files = ( 41 | C201748E1BD5509D00E4FE18 /* Comprehension.framework in Frameworks */, 42 | ); 43 | runOnlyForDeploymentPostprocessing = 0; 44 | }; 45 | /* End PBXFrameworksBuildPhase section */ 46 | 47 | /* Begin PBXGroup section */ 48 | 3789D1671FDE195000D7335E /* Comprehension */ = { 49 | isa = PBXGroup; 50 | children = ( 51 | 3789D1681FDE196100D7335E /* Comprehension.swift */, 52 | ); 53 | path = Comprehension; 54 | sourceTree = ""; 55 | }; 56 | C20174791BD5509D00E4FE18 = { 57 | isa = PBXGroup; 58 | children = ( 59 | C2C036F21C2B1A0B003FB853 /* Sources */, 60 | C2C037011C2B1A14003FB853 /* Tests */, 61 | C2C036D01C2B180D003FB853 /* Resources */, 62 | C20174841BD5509D00E4FE18 /* Products */, 63 | ); 64 | sourceTree = ""; 65 | }; 66 | C20174841BD5509D00E4FE18 /* Products */ = { 67 | isa = PBXGroup; 68 | children = ( 69 | C20174831BD5509D00E4FE18 /* Comprehension.framework */, 70 | C201748D1BD5509D00E4FE18 /* ComprehensionTests.xctest */, 71 | ); 72 | name = Products; 73 | sourceTree = ""; 74 | }; 75 | C207F6DA1D7F286700EBCC74 /* ComprehensionTests */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | 3789D16A1FDE197700D7335E /* ComprehensionTests.swift */, 79 | ); 80 | path = ComprehensionTests; 81 | sourceTree = ""; 82 | }; 83 | C2C036D01C2B180D003FB853 /* Resources */ = { 84 | isa = PBXGroup; 85 | children = ( 86 | C2C036D11C2B180D003FB853 /* Info.plist */, 87 | C2C036D21C2B180D003FB853 /* xcconfigs */, 88 | ); 89 | path = Resources; 90 | sourceTree = ""; 91 | }; 92 | C2C036D21C2B180D003FB853 /* xcconfigs */ = { 93 | isa = PBXGroup; 94 | children = ( 95 | C2C036D41C2B180D003FB853 /* UniversalFramework_Base.xcconfig */, 96 | C2C036D51C2B180D003FB853 /* UniversalFramework_Framework.xcconfig */, 97 | C2C036D61C2B180D003FB853 /* UniversalFramework_Test.xcconfig */, 98 | ); 99 | path = xcconfigs; 100 | sourceTree = ""; 101 | }; 102 | C2C036F21C2B1A0B003FB853 /* Sources */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | 3789D1671FDE195000D7335E /* Comprehension */, 106 | ); 107 | path = Sources; 108 | sourceTree = ""; 109 | }; 110 | C2C037011C2B1A14003FB853 /* Tests */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | C207F6DA1D7F286700EBCC74 /* ComprehensionTests */, 114 | ); 115 | path = Tests; 116 | sourceTree = ""; 117 | }; 118 | /* End PBXGroup section */ 119 | 120 | /* Begin PBXNativeTarget section */ 121 | C20174821BD5509D00E4FE18 /* Comprehension */ = { 122 | isa = PBXNativeTarget; 123 | buildConfigurationList = C20174971BD5509D00E4FE18 /* Build configuration list for PBXNativeTarget "Comprehension" */; 124 | buildPhases = ( 125 | C201747E1BD5509D00E4FE18 /* Sources */, 126 | ); 127 | buildRules = ( 128 | ); 129 | dependencies = ( 130 | ); 131 | name = Comprehension; 132 | productName = Comprehension; 133 | productReference = C20174831BD5509D00E4FE18 /* Comprehension.framework */; 134 | productType = "com.apple.product-type.framework"; 135 | }; 136 | C201748C1BD5509D00E4FE18 /* ComprehensionTests */ = { 137 | isa = PBXNativeTarget; 138 | buildConfigurationList = C201749A1BD5509D00E4FE18 /* Build configuration list for PBXNativeTarget "ComprehensionTests" */; 139 | buildPhases = ( 140 | C20174891BD5509D00E4FE18 /* Sources */, 141 | C201748A1BD5509D00E4FE18 /* Frameworks */, 142 | ); 143 | buildRules = ( 144 | ); 145 | dependencies = ( 146 | C20174901BD5509D00E4FE18 /* PBXTargetDependency */, 147 | ); 148 | name = ComprehensionTests; 149 | productName = ComprehensionTests; 150 | productReference = C201748D1BD5509D00E4FE18 /* ComprehensionTests.xctest */; 151 | productType = "com.apple.product-type.bundle.unit-test"; 152 | }; 153 | /* End PBXNativeTarget section */ 154 | 155 | /* Begin PBXProject section */ 156 | C201747A1BD5509D00E4FE18 /* Project object */ = { 157 | isa = PBXProject; 158 | attributes = { 159 | LastSwiftUpdateCheck = 0720; 160 | LastUpgradeCheck = 0900; 161 | TargetAttributes = { 162 | C20174821BD5509D00E4FE18 = { 163 | CreatedOnToolsVersion = 7.0; 164 | LastSwiftMigration = 0920; 165 | }; 166 | C201748C1BD5509D00E4FE18 = { 167 | CreatedOnToolsVersion = 7.0; 168 | LastSwiftMigration = 0920; 169 | }; 170 | }; 171 | }; 172 | buildConfigurationList = C201747D1BD5509D00E4FE18 /* Build configuration list for PBXProject "Comprehension" */; 173 | compatibilityVersion = "Xcode 8.0"; 174 | developmentRegion = English; 175 | hasScannedForEncodings = 0; 176 | knownRegions = ( 177 | en, 178 | ); 179 | mainGroup = C20174791BD5509D00E4FE18; 180 | productRefGroup = C20174841BD5509D00E4FE18 /* Products */; 181 | projectDirPath = ""; 182 | projectRoot = ""; 183 | targets = ( 184 | C20174821BD5509D00E4FE18 /* Comprehension */, 185 | C201748C1BD5509D00E4FE18 /* ComprehensionTests */, 186 | ); 187 | }; 188 | /* End PBXProject section */ 189 | 190 | /* Begin PBXSourcesBuildPhase section */ 191 | C201747E1BD5509D00E4FE18 /* Sources */ = { 192 | isa = PBXSourcesBuildPhase; 193 | buildActionMask = 2147483647; 194 | files = ( 195 | 3789D1691FDE196100D7335E /* Comprehension.swift in Sources */, 196 | ); 197 | runOnlyForDeploymentPostprocessing = 0; 198 | }; 199 | C20174891BD5509D00E4FE18 /* Sources */ = { 200 | isa = PBXSourcesBuildPhase; 201 | buildActionMask = 2147483647; 202 | files = ( 203 | 3789D16B1FDE197700D7335E /* ComprehensionTests.swift in Sources */, 204 | ); 205 | runOnlyForDeploymentPostprocessing = 0; 206 | }; 207 | /* End PBXSourcesBuildPhase section */ 208 | 209 | /* Begin PBXTargetDependency section */ 210 | C20174901BD5509D00E4FE18 /* PBXTargetDependency */ = { 211 | isa = PBXTargetDependency; 212 | target = C20174821BD5509D00E4FE18 /* Comprehension */; 213 | targetProxy = C201748F1BD5509D00E4FE18 /* PBXContainerItemProxy */; 214 | }; 215 | /* End PBXTargetDependency section */ 216 | 217 | /* Begin XCBuildConfiguration section */ 218 | C20174951BD5509D00E4FE18 /* Debug */ = { 219 | isa = XCBuildConfiguration; 220 | buildSettings = { 221 | ALWAYS_SEARCH_USER_PATHS = NO; 222 | COPY_PHASE_STRIP = NO; 223 | CURRENT_PROJECT_VERSION = 1; 224 | DEBUG_INFORMATION_FORMAT = dwarf; 225 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 226 | ONLY_ACTIVE_ARCH = YES; 227 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 228 | SWIFT_VERSION = 4.2; 229 | VERSIONING_SYSTEM = "apple-generic"; 230 | VERSION_INFO_PREFIX = ""; 231 | }; 232 | name = Debug; 233 | }; 234 | C20174961BD5509D00E4FE18 /* Release */ = { 235 | isa = XCBuildConfiguration; 236 | buildSettings = { 237 | ALWAYS_SEARCH_USER_PATHS = NO; 238 | COPY_PHASE_STRIP = NO; 239 | CURRENT_PROJECT_VERSION = 1; 240 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 241 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 242 | SWIFT_VERSION = 4.2; 243 | VALIDATE_PRODUCT = YES; 244 | VERSIONING_SYSTEM = "apple-generic"; 245 | VERSION_INFO_PREFIX = ""; 246 | }; 247 | name = Release; 248 | }; 249 | C20174981BD5509D00E4FE18 /* Debug */ = { 250 | isa = XCBuildConfiguration; 251 | baseConfigurationReference = C2C036D51C2B180D003FB853 /* UniversalFramework_Framework.xcconfig */; 252 | buildSettings = { 253 | APPLICATION_EXTENSION_API_ONLY = YES; 254 | CLANG_ENABLE_MODULES = YES; 255 | DEFINES_MODULE = YES; 256 | DYLIB_COMPATIBILITY_VERSION = 1; 257 | DYLIB_CURRENT_VERSION = 1; 258 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 259 | INFOPLIST_FILE = Resources/Info.plist; 260 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 261 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 262 | PRODUCT_BUNDLE_IDENTIFIER = ca.duan.Comprehension; 263 | PRODUCT_NAME = Comprehension; 264 | SKIP_INSTALL = YES; 265 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 266 | SWIFT_VERSION = 4.2; 267 | TVOS_DEPLOYMENT_TARGET = 9.0; 268 | }; 269 | name = Debug; 270 | }; 271 | C20174991BD5509D00E4FE18 /* Release */ = { 272 | isa = XCBuildConfiguration; 273 | baseConfigurationReference = C2C036D51C2B180D003FB853 /* UniversalFramework_Framework.xcconfig */; 274 | buildSettings = { 275 | APPLICATION_EXTENSION_API_ONLY = YES; 276 | CLANG_ENABLE_MODULES = YES; 277 | DEFINES_MODULE = YES; 278 | DYLIB_COMPATIBILITY_VERSION = 1; 279 | DYLIB_CURRENT_VERSION = 1; 280 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 281 | INFOPLIST_FILE = Resources/Info.plist; 282 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 283 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 284 | PRODUCT_BUNDLE_IDENTIFIER = ca.duan.Comprehension; 285 | PRODUCT_NAME = Comprehension; 286 | SKIP_INSTALL = YES; 287 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 288 | SWIFT_TREAT_WARNINGS_AS_ERRORS = YES; 289 | SWIFT_VERSION = 4.2; 290 | TVOS_DEPLOYMENT_TARGET = 9.0; 291 | }; 292 | name = Release; 293 | }; 294 | C201749B1BD5509D00E4FE18 /* Debug */ = { 295 | isa = XCBuildConfiguration; 296 | baseConfigurationReference = C2C036D61C2B180D003FB853 /* UniversalFramework_Test.xcconfig */; 297 | buildSettings = { 298 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 299 | CLANG_ENABLE_MODULES = YES; 300 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 301 | PRODUCT_BUNDLE_IDENTIFIER = ca.duan.ComprehensionTests; 302 | PRODUCT_NAME = "$(TARGET_NAME)"; 303 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 304 | SWIFT_SWIFT3_OBJC_INFERENCE = Off; 305 | SWIFT_VERSION = 4.2; 306 | }; 307 | name = Debug; 308 | }; 309 | C201749C1BD5509D00E4FE18 /* Release */ = { 310 | isa = XCBuildConfiguration; 311 | baseConfigurationReference = C2C036D61C2B180D003FB853 /* UniversalFramework_Test.xcconfig */; 312 | buildSettings = { 313 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 314 | CLANG_ENABLE_MODULES = YES; 315 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 316 | PRODUCT_BUNDLE_IDENTIFIER = ca.duan.ComprehensionTests; 317 | PRODUCT_NAME = "$(TARGET_NAME)"; 318 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 319 | SWIFT_SWIFT3_OBJC_INFERENCE = Off; 320 | SWIFT_TREAT_WARNINGS_AS_ERRORS = YES; 321 | SWIFT_VERSION = 4.2; 322 | }; 323 | name = Release; 324 | }; 325 | /* End XCBuildConfiguration section */ 326 | 327 | /* Begin XCConfigurationList section */ 328 | C201747D1BD5509D00E4FE18 /* Build configuration list for PBXProject "Comprehension" */ = { 329 | isa = XCConfigurationList; 330 | buildConfigurations = ( 331 | C20174951BD5509D00E4FE18 /* Debug */, 332 | C20174961BD5509D00E4FE18 /* Release */, 333 | ); 334 | defaultConfigurationIsVisible = 0; 335 | defaultConfigurationName = Release; 336 | }; 337 | C20174971BD5509D00E4FE18 /* Build configuration list for PBXNativeTarget "Comprehension" */ = { 338 | isa = XCConfigurationList; 339 | buildConfigurations = ( 340 | C20174981BD5509D00E4FE18 /* Debug */, 341 | C20174991BD5509D00E4FE18 /* Release */, 342 | ); 343 | defaultConfigurationIsVisible = 0; 344 | defaultConfigurationName = Release; 345 | }; 346 | C201749A1BD5509D00E4FE18 /* Build configuration list for PBXNativeTarget "ComprehensionTests" */ = { 347 | isa = XCConfigurationList; 348 | buildConfigurations = ( 349 | C201749B1BD5509D00E4FE18 /* Debug */, 350 | C201749C1BD5509D00E4FE18 /* Release */, 351 | ); 352 | defaultConfigurationIsVisible = 0; 353 | defaultConfigurationName = Release; 354 | }; 355 | /* End XCConfigurationList section */ 356 | }; 357 | rootObject = C201747A1BD5509D00E4FE18 /* Project object */; 358 | } 359 | -------------------------------------------------------------------------------- /Comprehension.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Comprehension.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Comprehension.xcodeproj/xcshareddata/xcschemes/Comprehension.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 65 | 71 | 72 | 73 | 74 | 75 | 76 | 82 | 83 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Comprehension contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | export HOMEBREW_NO_AUTO_UPDATE = 1 2 | export SWIFTENV_ROOT := $(HOME)/.swiftenv 3 | export PATH := $(SWIFTENV_ROOT)/bin:$(SWIFTENV_ROOT)/shims:$(PATH) 4 | 5 | install-carthage: 6 | brew remove carthage --force || true 7 | brew install carthage 8 | 9 | install-swiftpm-linux: 10 | git clone --depth 1 https://github.com/kylef/swiftenv.git ~/.swiftenv 11 | swiftenv install -s 12 | 13 | install-%: 14 | true 15 | 16 | test-iOS: 17 | set -o pipefail && \ 18 | xcodebuild \ 19 | -project Comprehension.xcodeproj \ 20 | -scheme Comprehension \ 21 | -configuration Release \ 22 | -destination "name=iPhone X,OS=12.0" \ 23 | test 24 | 25 | test-macOS: 26 | set -o pipefail && \ 27 | xcodebuild \ 28 | -project Comprehension.xcodeproj \ 29 | -scheme Comprehension \ 30 | -configuration Release \ 31 | test 32 | 33 | test-tvOS: 34 | set -o pipefail && \ 35 | xcodebuild \ 36 | -project Comprehension.xcodeproj \ 37 | -scheme Comprehension \ 38 | -configuration Release \ 39 | -destination "platform=tvOS Simulator,name=Apple TV,OS=12.0" \ 40 | test 41 | 42 | test-carthage: 43 | set -o pipefail && \ 44 | carthage build \ 45 | --no-skip-current \ 46 | --configuration Release \ 47 | --verbose 48 | ls Carthage/build/Mac/Comprehension.framework 49 | ls Carthage/build/iOS/Comprehension.framework 50 | ls Carthage/build/tvOS/Comprehension.framework 51 | ls Carthage/build/watchOS/Comprehension.framework 52 | 53 | test-swiftpm-macOS: 54 | swift test 55 | 56 | test-swiftpm-linux: 57 | swift test 58 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:4.2 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "Comprehension", 7 | products: [ 8 | .library( 9 | name: "Comprehension", 10 | targets: ["Comprehension"]), 11 | ], 12 | targets: [ 13 | .target( 14 | name: "Comprehension", 15 | dependencies: []), 16 | .testTarget( 17 | name: "ComprehensionTests", 18 | dependencies: ["Comprehension"]), 19 | ] 20 | ) 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Comprehension 2 | 3 | This library provides [List Comprehension][1] for Swift. Like so: 4 | 5 | ```swift 6 | let numbers = [1, 2, 3] 7 | let letters = "ab" 8 | 9 | // produces ["a1", "a2", "a3", "b1", "b2", "b3"] 10 | Array(letters, numbers) { "\($0)\($1)" } 11 | 12 | // produces ["a1", "a3", "b1", "b3"] 13 | Array(letters, numbers, where: { $1 % 2 != 0 }) { "\($0)\($1)" } 14 | ``` 15 | 16 | ## Installation 17 | 18 | ### Swift Package Manager 19 | 20 | ```swift 21 | .package(url: "git@github.com:dduan/Comprehension.git", .branch("master")), 22 | 23 | ``` 24 | 25 | (and `"Comprehension"` to the target's dependencies.) 26 | 27 | ### CocoaPods 28 | 29 | ``` 30 | use_frameworks! 31 | 32 | pod "Comprehension" 33 | ``` 34 | 35 | ### Carthage 36 | 37 | ``` 38 | github "dduan/Comprehension" 39 | ``` 40 | 41 | ### Direct Embed 42 | 43 | Include `Sources/Comprehension/Comprehension.swift` in your project. 44 | 45 | ## What's List Comprehension? 46 | 47 | List comprehension is a powerful syntax for processing lists in languages such as Haskell, Python, etc. It's 48 | particularly handy when you need to deal with combinations of each elements in multiple lists (their 49 | [Cartesian product][2]). 50 | 51 | The origin of list comprehension is often attribute to set comprehension in mathematics, whereas 52 | 53 | ``` 54 | {2·x|x ∈ ℕ, x ≤ 10} 55 | ``` 56 | 57 | … means "take all integers (element of set ℕ) that are less that 10, multiply each by 2 and form a new 58 | set with the results." 59 | 60 | Here's an example of how list comprehension works in Haskell: 61 | 62 | ```haskell 63 | ghci> [x+y | x <- [1,2,3], y <- [10,100,1000]] 64 | [11,101,1001,12,102,1002,13,103,1003] 65 | ``` 66 | 67 | Here, integers from one list is sequentially paired with that from the other list, resulting in 68 | 3 * 3 = 9 pairs. The sum of each pair forms the resulting list of integers. 69 | 70 | Comprehension on a single list is equivalent of `list.filter(f).map(g)`. When input is 2 lists: 71 | 72 | ```swift 73 | // Comprehension syntax 74 | let result = Array(list0, list1, where: f) { g($0, $1) } 75 | ``` 76 | 77 | … is equivalent of … 78 | 79 | ```swift 80 | var result = [TypeOfElementInList0, TypeOfElementInList1]() 81 | for e0 in list0 { 82 | for e1 in list1 { 83 | if f(e0, e1) { 84 | result.append(g(e0, e1)) 85 | } 86 | } 87 | } 88 | // The fact that `result` is a var is not equivalent, but 🤷‍♀️. 89 | ``` 90 | 91 | … or in functional style … 92 | 93 | ```swift 94 | let result = list0 95 | .map { e0 in 96 | list1.map { e1 in 97 | (e0, e1) 98 | } 99 | } 100 | .joined() 101 | .filter(f) 102 | .map(g) 103 | ``` 104 | 105 | Note how the list comprehension version is much more concise above. And imagine expanding the example to 3, 4, 106 | 5 lists! 107 | 108 | ## License 109 | 110 | MIT, see [LICENSE][3]. 111 | 112 | [1]: https://en.wikipedia.org/wiki/List_comprehension 113 | [2]: https://en.wikipedia.org/wiki/Cartesian_product 114 | [3]: https://github.com/dduan/Comprehension/blob/master/LICENSE.md 115 | -------------------------------------------------------------------------------- /Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 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 | 0.0.3 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Resources/xcconfigs/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Marius Rackwitz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Resources/xcconfigs/UniversalFramework_Base.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // Put this file alongside to the other both, as it contains what 3 | // both have in common. Don't rename this file. 4 | // 5 | // Copyright (c) 2014-2015 Marius Rackwitz. All rights reserved. 6 | // 7 | 8 | // Make it universal 9 | SUPPORTED_PLATFORMS = macosx iphonesimulator iphoneos watchos watchsimulator appletvos appletvsimulator 10 | VALID_ARCHS[sdk=macosx*] = i386 x86_64 11 | VALID_ARCHS[sdk=iphoneos*] = arm64 armv7 armv7s 12 | VALID_ARCHS[sdk=iphonesimulator*] = i386 x86_64 13 | VALID_ARCHS[sdk=watchos*] = armv7k 14 | VALID_ARCHS[sdk=watchsimulator*] = i386 15 | VALID_ARCHS[sdk=appletv*] = arm64 16 | VALID_ARCHS[sdk=appletvsimulator*] = x86_64 17 | 18 | // Dynamic linking uses different default copy paths 19 | LD_RUNPATH_SEARCH_PATHS[sdk=macosx*] = $(inherited) '@executable_path/../Frameworks' '@loader_path/Frameworks' 20 | LD_RUNPATH_SEARCH_PATHS[sdk=iphoneos*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 21 | LD_RUNPATH_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 22 | LD_RUNPATH_SEARCH_PATHS[sdk=watchos*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 23 | LD_RUNPATH_SEARCH_PATHS[sdk=watchsimulator*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 24 | LD_RUNPATH_SEARCH_PATHS[sdk=appletvos*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 25 | LD_RUNPATH_SEARCH_PATHS[sdk=appletvsimulator*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 26 | -------------------------------------------------------------------------------- /Resources/xcconfigs/UniversalFramework_Framework.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // Inherit from this config in your framework target. 3 | // 4 | // Copyright (c) 2014-2015 Marius Rackwitz. All rights reserved. 5 | // 6 | 7 | #include "UniversalFramework_Base.xcconfig" 8 | 9 | // OSX-specific default settings 10 | FRAMEWORK_VERSION[sdk=macosx*] = A 11 | COMBINE_HIDPI_IMAGES[sdk=macosx*] = YES 12 | 13 | // iOS-specific default settings 14 | CODE_SIGN_IDENTITY[sdk=iphoneos*] = iPhone Developer 15 | TARGETED_DEVICE_FAMILY[sdk=iphonesimulator*] = 1,2 16 | TARGETED_DEVICE_FAMILY[sdk=iphone*] = 1,2 17 | 18 | // TV-specific default settings 19 | TARGETED_DEVICE_FAMILY[sdk=appletvsimulator*] = 3 20 | TARGETED_DEVICE_FAMILY[sdk=appletv*] = 3 21 | 22 | // Watch-specific default settings 23 | TARGETED_DEVICE_FAMILY[sdk=watchsimulator*] = 4 24 | TARGETED_DEVICE_FAMILY[sdk=watch*] = 4 25 | 26 | ENABLE_BITCODE[sdk=macosx*] = NO 27 | ENABLE_BITCODE[sdk=watchsimulator*] = YES 28 | ENABLE_BITCODE[sdk=watch*] = YES 29 | ENABLE_BITCODE[sdk=iphonesimulator*] = YES 30 | ENABLE_BITCODE[sdk=iphone*] = YES 31 | ENABLE_BITCODE[sdk=appletvsimulator*] = YES 32 | ENABLE_BITCODE[sdk=appletv*] = YES 33 | -------------------------------------------------------------------------------- /Resources/xcconfigs/UniversalFramework_Test.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // Inherit from this config in the test target for your framework. 3 | // 4 | // Copyright (c) 2014-2015 Marius Rackwitz. All rights reserved. 5 | // 6 | 7 | #include "UniversalFramework_Base.xcconfig" 8 | 9 | FRAMEWORK_SEARCH_PATHS = $(inherited) '$(PLATFORM_DIR)/Developer/Library/Frameworks' 10 | 11 | // Yep. 12 | LD_RUNPATH_SEARCH_PATHS[sdk=macosx*] = $(inherited) '@executable_path/../Frameworks' '@loader_path/../Frameworks' 13 | LD_RUNPATH_SEARCH_PATHS[sdk=iphoneos*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 14 | LD_RUNPATH_SEARCH_PATHS[sdk=iphonesimulator*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 15 | LD_RUNPATH_SEARCH_PATHS[sdk=watchos*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 16 | LD_RUNPATH_SEARCH_PATHS[sdk=watchsimulator*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 17 | LD_RUNPATH_SEARCH_PATHS[sdk=appletvos*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 18 | LD_RUNPATH_SEARCH_PATHS[sdk=appletvsimulator*] = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 19 | -------------------------------------------------------------------------------- /Sources/Comprehension/Comprehension.swift: -------------------------------------------------------------------------------- 1 | extension Array { 2 | public init< 3 | E0, 4 | S0 5 | >( 6 | _ s0: S0, 7 | where predicate: ((E0) -> Bool)? = nil, 8 | transform: (E0) -> Element 9 | ) where 10 | S0: Collection, S0.Element == E0 11 | { 12 | self.init() 13 | self.reserveCapacity(s0.underestimatedCount) 14 | for e0 in s0 { 15 | if predicate?(e0) ?? true { 16 | self.append(transform(e0)) 17 | } 18 | } 19 | } 20 | 21 | public init< 22 | E0, E1, 23 | S0, S1 24 | >( 25 | _ s0: S0, 26 | _ s1: S1, 27 | where predicate: ((E0, E1) -> Bool)? = nil, 28 | transform: (E0, E1) -> Element 29 | ) where 30 | S0: Collection, S0.Element == E0, 31 | S1: Collection, S1.Element == E1 32 | { 33 | self.init() 34 | self.reserveCapacity(s0.underestimatedCount * s1.underestimatedCount) 35 | for e0 in s0 { 36 | for e1 in s1 { 37 | if predicate?(e0, e1) ?? true { 38 | self.append(transform(e0, e1)) 39 | } 40 | }} 41 | } 42 | 43 | public init< 44 | E0, E1, E2, 45 | S0, S1, S2 46 | >( 47 | _ s0: S0, 48 | _ s1: S1, 49 | _ s2: S2, 50 | where predicate: ((E0, E1, E2) -> Bool)? = nil, 51 | transform: (E0, E1, E2) -> Element 52 | ) where 53 | S0: Collection, S0.Element == E0, 54 | S1: Collection, S1.Element == E1, 55 | S2: Collection, S2.Element == E2 56 | { 57 | self.init() 58 | self.reserveCapacity( 59 | s0.underestimatedCount * 60 | s1.underestimatedCount * 61 | s2.underestimatedCount 62 | ) 63 | for e0 in s0 { 64 | for e1 in s1 { 65 | for e2 in s2 { 66 | if predicate?(e0, e1, e2) ?? true { 67 | self.append(transform(e0, e1, e2)) 68 | } 69 | }}} 70 | } 71 | 72 | public init< 73 | E0, E1, E2, E3, 74 | S0, S1, S2, S3 75 | >( 76 | _ s0: S0, 77 | _ s1: S1, 78 | _ s2: S2, 79 | _ s3: S3, 80 | where predicate: ((E0, E1, E2, E3) -> Bool)? = nil, 81 | transform: (E0, E1, E2, E3) -> Element 82 | ) where 83 | S0: Collection, S0.Element == E0, 84 | S1: Collection, S1.Element == E1, 85 | S2: Collection, S2.Element == E2, 86 | S3: Collection, S3.Element == E3 87 | { 88 | self.init() 89 | self.reserveCapacity( 90 | s0.underestimatedCount * 91 | s1.underestimatedCount * 92 | s2.underestimatedCount * 93 | s3.underestimatedCount 94 | ) 95 | for e0 in s0 { 96 | for e1 in s1 { 97 | for e2 in s2 { 98 | for e3 in s3 { 99 | if predicate?(e0, e1, e2, e3) ?? true { 100 | self.append(transform(e0, e1, e2, e3)) 101 | } 102 | }}}} 103 | } 104 | 105 | public init< 106 | E0, E1, E2, E3, E4, 107 | S0, S1, S2, S3, S4 108 | >( 109 | _ s0: S0, 110 | _ s1: S1, 111 | _ s2: S2, 112 | _ s3: S3, 113 | _ s4: S4, 114 | where predicate: ((E0, E1, E2, E3, E4) -> Bool)? = nil, 115 | transform: (E0, E1, E2, E3, E4) -> Element 116 | ) where 117 | S0: Collection, S0.Element == E0, 118 | S1: Collection, S1.Element == E1, 119 | S2: Collection, S2.Element == E2, 120 | S3: Collection, S3.Element == E3, 121 | S4: Collection, S4.Element == E4 122 | { 123 | self.init() 124 | self.reserveCapacity( 125 | s0.underestimatedCount * 126 | s1.underestimatedCount * 127 | s2.underestimatedCount * 128 | s3.underestimatedCount * 129 | s4.underestimatedCount 130 | ) 131 | 132 | for e0 in s0 { 133 | for e1 in s1 { 134 | for e2 in s2 { 135 | for e3 in s3 { 136 | for e4 in s4 { 137 | if predicate?(e0, e1, e2, e3, e4) ?? true { 138 | self.append(transform(e0, e1, e2, e3, e4)) 139 | } 140 | }}}}} 141 | } 142 | 143 | public init< 144 | E0, E1, E2, E3, E4, E5, 145 | S0, S1, S2, S3, S4, S5 146 | >( 147 | _ s0: S0, 148 | _ s1: S1, 149 | _ s2: S2, 150 | _ s3: S3, 151 | _ s4: S4, 152 | _ s5: S5, 153 | where predicate: ((E0, E1, E2, E3, E4, E5) -> Bool)? = nil, 154 | transform: (E0, E1, E2, E3, E4, E5) -> Element 155 | ) where 156 | S0: Collection, S0.Element == E0, 157 | S1: Collection, S1.Element == E1, 158 | S2: Collection, S2.Element == E2, 159 | S3: Collection, S3.Element == E3, 160 | S4: Collection, S4.Element == E4, 161 | S5: Collection, S5.Element == E5 162 | { 163 | self.init() 164 | self.reserveCapacity( 165 | s0.underestimatedCount * 166 | s1.underestimatedCount * 167 | s2.underestimatedCount * 168 | s3.underestimatedCount * 169 | s4.underestimatedCount * 170 | s5.underestimatedCount 171 | ) 172 | 173 | for e0 in s0 { 174 | for e1 in s1 { 175 | for e2 in s2 { 176 | for e3 in s3 { 177 | for e4 in s4 { 178 | for e5 in s5 { 179 | if predicate?(e0, e1, e2, e3, e4, e5) ?? true { 180 | self.append(transform(e0, e1, e2, e3, e4, e5)) 181 | } 182 | }}}}}} 183 | } 184 | 185 | public init< 186 | E0, E1, E2, E3, E4, E5, E6, 187 | S0, S1, S2, S3, S4, S5, S6 188 | >( 189 | _ s0: S0, 190 | _ s1: S1, 191 | _ s2: S2, 192 | _ s3: S3, 193 | _ s4: S4, 194 | _ s5: S5, 195 | _ s6: S6, 196 | where predicate: ((E0, E1, E2, E3, E4, E5, E6) -> Bool)? = nil, 197 | transform: (E0, E1, E2, E3, E4, E5, E6) -> Element 198 | ) where 199 | S0: Collection, S0.Element == E0, 200 | S1: Collection, S1.Element == E1, 201 | S2: Collection, S2.Element == E2, 202 | S3: Collection, S3.Element == E3, 203 | S4: Collection, S4.Element == E4, 204 | S5: Collection, S5.Element == E5, 205 | S6: Collection, S6.Element == E6 206 | { 207 | self.init() 208 | self.reserveCapacity( 209 | s0.underestimatedCount * 210 | s1.underestimatedCount * 211 | s2.underestimatedCount * 212 | s3.underestimatedCount * 213 | s4.underestimatedCount * 214 | s5.underestimatedCount * 215 | s6.underestimatedCount 216 | ) 217 | 218 | for e0 in s0 { 219 | for e1 in s1 { 220 | for e2 in s2 { 221 | for e3 in s3 { 222 | for e4 in s4 { 223 | for e5 in s5 { 224 | for e6 in s6 { 225 | if predicate?(e0, e1, e2, e3, e4, e5, e6) ?? true { 226 | self.append(transform(e0, e1, e2, e3, e4, e5, e6)) 227 | } 228 | }}}}}}} 229 | } 230 | } 231 | -------------------------------------------------------------------------------- /Tests/ComprehensionTests/ComprehensionTests.swift: -------------------------------------------------------------------------------- 1 | import Comprehension 2 | import XCTest 3 | 4 | class ComprehensionTests: XCTestCase { 5 | func testMixedTypedComprehension() { 6 | let numbers = [1, 2, 3] 7 | let letters = "abcd" 8 | let letterEven = Array(letters, numbers, where: { $1 % 2 == 0 }) { "\($0)\($1)" } 9 | XCTAssertEqual(["a2", "b2", "c2", "d2"], letterEven) 10 | } 11 | 12 | func testOneDimentionalComprehension() { 13 | XCTAssertEqual(Array([1, 2, 3]) { $0 + 1 }, [2, 3, 4]) 14 | XCTAssertEqual(Array([1, 2, 3], where: { $0 % 2 == 0 }) { $0 + 1 }, [3]) 15 | } 16 | 17 | func testTwoDimentionalComprehension() { 18 | XCTAssertEqual( 19 | Array([1, 2, 3], [100, 200, 300]) { $0 + $1 }, 20 | [101, 201, 301, 102, 202, 302, 103, 203, 303] 21 | ) 22 | 23 | let s0 = [1, 2, 3] 24 | let s1 = [10, 20, 30] 25 | XCTAssertEqual([Int](s0, s1, where: { $0 < 2 && ($1 / 10) % 2 == 0 }) { $0 + $1 }, [21]) 26 | } 27 | 28 | func testThreeDimentionalComprehension() { 29 | XCTAssertEqual( 30 | Array([1, 2], [30, 40], [500, 600]) { $0 + $1 + $2 }, 31 | [531, 631, 541, 641, 532, 632, 542, 642] 32 | ) 33 | 34 | let s0 = [1, 2] 35 | let s1 = [30, 40] 36 | let s2 = [500, 600] 37 | XCTAssertEqual( 38 | [Int](s0, s1, s2, where: { $0 < 2 && ($2 / 100) % 2 == 0 }) { $0 + $1 + $2 }, 39 | [631, 641] 40 | ) 41 | } 42 | 43 | func testFourDimentionalComprehension() { 44 | XCTAssertEqual( 45 | Array([1, 2], [30, 40], [500, 600], [7000]) { $0 + $1 + $2 + $3 }, 46 | [7531, 7631, 7541, 7641, 7532, 7632, 7542, 7642] 47 | ) 48 | 49 | let s0 = [1, 2] 50 | let s1 = [30] 51 | let s2 = [500] 52 | let s3 = [7000, 8000] 53 | XCTAssertEqual( 54 | [Int](s0, s1, s2, s3, where: { $3 > 7000 }) { $0 + $1 + $2 + $3 }, 55 | [8531, 8532] 56 | ) 57 | } 58 | 59 | func testFiveDimentionalComprehension() { 60 | let sum: (Int, Int, Int, Int, Int) -> Int = { $0 + $1 + $2 + $3 + $4 } 61 | XCTAssertEqual( 62 | Array([1, 2], [30], [500], [7000], [80000], transform: sum), 63 | [87531, 87532] 64 | ) 65 | 66 | let s0 = [1, 2] 67 | let s1 = [30] 68 | let s2 = [400] 69 | let s3 = [5000] 70 | let s4 = [60000, 70000] 71 | let filter: (Int, Int, Int, Int, Int) -> Bool = { $4 < 70000 } 72 | XCTAssertEqual( 73 | [Int](s0, s1, s2, s3, s4, where: filter) { $0 + $1 + $2 + $3 + $4 }, 74 | [65431, 65432] 75 | ) 76 | } 77 | 78 | static var allTests = [ 79 | ("testMixedTypedComprehension", testMixedTypedComprehension), 80 | ("testOneDimentionalComprehension", testOneDimentionalComprehension), 81 | ("testTwoDimentionalComprehension", testTwoDimentionalComprehension), 82 | ("testThreeDimentionalComprehension", testThreeDimentionalComprehension), 83 | ("testFourDimentionalComprehension", testFourDimentionalComprehension), 84 | ("testFiveDimentionalComprehension", testFiveDimentionalComprehension), 85 | ] 86 | } 87 | -------------------------------------------------------------------------------- /Tests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import ComprehensionTests 3 | 4 | XCTMain([ 5 | testCase(ComprehensionTests.allTests), 6 | ]) 7 | --------------------------------------------------------------------------------