![🐤 3.0: ready](https://img.shields.io/badge/🐤 3.0-ready-red.svg) ![Platform OS X | iOS | tvOS | watchOS | Linux](https://img.shields.io/badge/platform-OS X | iOS | tvOS | watchOS | Linux-orange.svg) ![GitHub license](https://img.shields.io/badge/license-Apache 2.0-lightgrey.svg)
Swift boilerplate code library with tons of useful stuff, including Linux compatibility layers and functional compositions
Boilerplate library was mainly introduced to fulfill the needs of Swift Express - web application server side framework for Swift. Now it's a part of Crossroad Labs Foundation.
Still we hope it will be useful for everybody else.
May less boilerplate code be with you ;)
Add the following dependency to your Package.swift:
.Package(url: "https://github.com/crossroadlabs/Boilerplate.git", majorVersion: 0)
Run swift build
and build your app. Package manager is supported on OS X, but it's still recommended to be used on Linux only.
Add the following to your Cartfile:
github "crossroadlabs/Boilerplate"
Run carthage update
and follow the steps as described in Carthage's README.
Add the following to your Podfile:
pod 'Boilerplate'
Make sure that you are integrating your dependencies using frameworks: add use_frameworks!
to your Podfile. Then run pod install
.
Swift 3.0 has a pretty much different API in standard library from Swift 2.2. You can import Boilerplate and the code below (Swift 3.0 style) will just work with your Swift 2.2 compiler:
var array = ["a", "b", "c"]
array.append(contentsOf: ["e"]) //this is not correct in Swift 2.2 without Boilerplate
Just a quick example, showing how easy it is to manage different time APIs with Timeout:
let to = Timeout.Infinity
XCTAssertEqual(to.timeSinceNow(), NSDate.distantFuture())
XCTAssertEqual(to.timeInterval, Double.infinity)
//convert to NSTimeInterval
to.timeInterval
//convert to NSDate
to.timeSinceNow()
//convert to dispatch_time_t
to.dispatchTime
The idea behind is to transform (A, B, C...)->Z
to (A)->(B)->(C)->...->Z
, which is called currying und uncurrying respectively.
func ftwo(b:Bool, i:Int) -> String {
return String(b) + "_" + String(i)
}
let ctwo = curry(ftwo)
print(ctwo(true)(1)) //call curried function
let utwo = uncurry(ctwo)
print(utwo(false, 0)) //uncurried back works as expected
Allows to partieally or fully apply a function with tuple:
func fthree(b:Bool, i:Int, d:Double) -> String {
return String(b) + "_" + String(i) + "_" + String(d)
}
let fbi = (__, __, 1.0) |> fthree //operator way, __ stands for an argument
//you don't want to apply right now.
let fi = (true, __, 1.0) |> fthree //operator way
let fd = apply(args: (true, 1, _), to: fthree) //function way
print(fbi(false, 0)) //prints "false_0_1.0"
print(fi(0)) //prints "true_0_1.0"
print(fd(0.0)) //prints "true_1_0.0"
print((false, 0, 0.0) |> fthree) //full apply, prints "false_0_0.0"
Works like apply, though weakly. I.e. the argument passed is not retained. For now works with single argument only. Is a lot useful within UIViewController
to avoid retension of self
:
//func inside UIViewController
//just imagine it does something very important
func mymagicfunc(s:String) {
print(self, s)
}
//your very advanced int formatting dependent on self
func myintformat(i:Int) -> String {
return self._formatWith(self._format, i)
}
//you can safely do that and self is not retained
//any calls to self._myprocstored will just do nothing if self isn't there anymore
self._myprocstored = self ~> ViewController.mymagicfunc
//format now has a signature of `(Int)->String?`; ? is not a mistake
let format = self ~> ViewController.myintformat
format is a special function here. Which will return a value is self
exists and nil
if doesn't. The return value is changed to Optional
.
OK, you have a tuple of like ((A, B), C)
, but you need (A, B, C)? This is called tuple flattening and can be done with:
let t = ((true, 1), 1.0)
flatten(t) //here you get: (true, 1, 1.0)
Unfortunately it's no longer possible in Swift to apply tuple to a function with several argumens. You can do it with boilerplate apply
(|>
operator form) or tuplify a function:
func fthree(b:Bool, i:Int, d:Double) -> String {
return String(b) + "_" + String(i) + "_" + String(d)
}
let tuple = (false, 1, 0.0)
print(tuplify(fthree)(tuple)) //prints "false_1_0.0"
Examples above are just a quick intro to what Boilerplate can bring you. Take a look inside and see yourself. It handles NS Bridging and exact type comparison in case you want to avoid Automatic Bridging, some Funtional extensions, CF Bridging, Error Handling including low level C APIs Error Handling, Collections Routines i.e. Collections Zipping, Crossplatform Threads and much more.
Contributions are welcome. Let's get rid of boilerplate code in Swift together.
- v0.2.3
- Renamed zip to zipWith(other:) not to collide with built in zip
- v0.2.2
- Minor Swift 3.0 Array fixes
- v0.2.1
- Range shims for Swift 3.0
- v0.2.0
- Swift 3.0 preview 1 support
- Null pointers workarounds (Swift 3.0/2.x related)
- v0.1.x:
- Obj-C Bridging utils
- Fatal errors
- C error handling
- AnyError
- ZippedSequence
- NonStrictEquatable
- Timeout (and conversion to different formats)
- tiny ThreadLocal and Thread
- Tasks
- Invalidation tokens
- Swift 3.0 shimming
- Linux/Mac incompatibilities fixes
To get started, sign the Contributor License Agreement.