Skip to content

Instantly share code, notes, and snippets.

@beccadax
Last active July 8, 2017 12:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save beccadax/7d6b1e54ab13f3859227e4dc613b354c to your computer and use it in GitHub Desktop.
Save beccadax/7d6b1e54ab13f3859227e4dc613b354c to your computer and use it in GitHub Desktop.
Explicit conversion operator for Swift.
import Foundation
import ExplicitlyConvertible
let i8: Int8 = 8
let i64: Int64 = 64
i64 + ^i8 // => 72
struct Person {
var name: String
var birthDate: Date
}
let people: [Person] = []
let names = people.map(^\.name)
type(of: names) // => Array<String>
prefix operator ^
/// Conforming types can be unconditionally, losslessly converted to
/// another type through the explicit conversion operator, `^`.
public protocol ExplicitlyConvertible {
associatedtype ExplicitConversionSupertype
/// Converts `self` to an equivalent supertype, such as a wider
/// integer type.
static prefix func ^(operand: Self) -> ExplicitConversionSupertype
}
// Operators below this point simply let you indirectly convert through
// several explicit supertypes at once. Five is an arbitrary choice; it
// just happens to be more than high enough to get you from the
// smallest integers to the largest.
extension ExplicitlyConvertible where ExplicitConversionSupertype: ExplicitlyConvertible {
public static prefix func ^(operand: Self) -> ExplicitConversionSupertype.ExplicitConversionSupertype {
return ^(^operand)
}
}
extension ExplicitlyConvertible where ExplicitConversionSupertype: ExplicitlyConvertible, ExplicitConversionSupertype.ExplicitConversionSupertype: ExplicitlyConvertible {
public static prefix func ^(operand: Self) -> ExplicitConversionSupertype.ExplicitConversionSupertype.ExplicitConversionSupertype {
return ^(^(^operand))
}
}
extension ExplicitlyConvertible where ExplicitConversionSupertype: ExplicitlyConvertible, ExplicitConversionSupertype.ExplicitConversionSupertype: ExplicitlyConvertible, ExplicitConversionSupertype.ExplicitConversionSupertype.ExplicitConversionSupertype: ExplicitlyConvertible {
public static prefix func ^(operand: Self) -> ExplicitConversionSupertype.ExplicitConversionSupertype.ExplicitConversionSupertype.ExplicitConversionSupertype {
return ^(^(^(^operand)))
}
}
extension ExplicitlyConvertible where ExplicitConversionSupertype: ExplicitlyConvertible, ExplicitConversionSupertype.ExplicitConversionSupertype: ExplicitlyConvertible, ExplicitConversionSupertype.ExplicitConversionSupertype.ExplicitConversionSupertype: ExplicitlyConvertible, ExplicitConversionSupertype.ExplicitConversionSupertype.ExplicitConversionSupertype.ExplicitConversionSupertype: ExplicitlyConvertible {
public static prefix func ^(operand: Self) -> ExplicitConversionSupertype.ExplicitConversionSupertype.ExplicitConversionSupertype.ExplicitConversionSupertype.ExplicitConversionSupertype {
return ^(^(^(^(^operand))))
}
}
extension Int8: ExplicitlyConvertible {
public typealias ExplicitConversionSupertype = Int16
}
extension Int16: ExplicitlyConvertible {
public typealias ExplicitConversionSupertype = Int32
}
extension Int32: ExplicitlyConvertible {
public typealias ExplicitConversionSupertype = Int
}
extension Int: ExplicitlyConvertible {
public typealias ExplicitConversionSupertype = Int64
}
extension UInt8: ExplicitlyConvertible {
public typealias ExplicitConversionSupertype = UInt16
}
extension UInt16: ExplicitlyConvertible {
public typealias ExplicitConversionSupertype = UInt32
}
extension UInt32: ExplicitlyConvertible {
public typealias ExplicitConversionSupertype = UInt
}
extension UInt: ExplicitlyConvertible {
public typealias ExplicitConversionSupertype = UInt64
}
extension ExplicitlyConvertible where Self: BinaryInteger, ExplicitConversionSupertype: BinaryInteger {
/// Converts the integer to a wider integer type.
public static prefix func ^(operand: Self) -> ExplicitConversionSupertype {
return ExplicitConversionSupertype(operand)
}
}
extension KeyPath: ExplicitlyConvertible {
public typealias ExplicitConversionSupertype = (Root) -> Value
/// Converts the KeyPath to a getter function.
public static prefix func ^(operand: KeyPath<Root, Value>) -> (Root) -> Value {
return { $0[keyPath: operand] }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment