Skip to content

Instantly share code, notes, and snippets.

@rnapier
Last active February 3, 2018 22:59
Show Gist options
  • Save rnapier/c4b91c4372115f9b5542 to your computer and use it in GitHub Desktop.
Save rnapier/c4b91c4372115f9b5542 to your computer and use it in GitHub Desktop.
Another Swift box for [Protocol]
// Yet another Swift box....
// I had never run into this explicitly until Andrew Spiess (@ninjazoete) asked about it a couple of days ago:
// https://twitter.com/ninjazoete/status/669530132919525377
// Now it's springing up all over the place in my work.
//
// I'm calling it "map-$0-boxing" for the moment ("identity boxing" is more accurate, but "map-$0" better
// matches the actual code). Anyone have a better or clearer implementation?
//
// I completely get why it's necessary currently (@jckarter confirmed [Type] and [Protocol] are stored
// differently), but it's not really obvious to the reader, so wondering if people should just learn to
// read it, or we should come up with a better way to write it.
protocol ProductType {}
struct Milk: ProductType {}
let milks = [Milk()]
//
// There's the map-0 box. It "boxes" the conforming type into the protocol
//
let products: [ProductType] = milks.map{$0}
//
//
//
// I've been contemplating something like these, but I don't think there's any way to type-parameterize
// on protocols in Swift, either in functions or in extensions
// func castArrayToProtocol<T, P where T:P>(xs: [T]) -> [P] { return xs.map{$0} }
//
// extension Array where Element: P {
// func castToProtocol() -> [P] { return map{$0} }
// }
// There's this solution, but I hate it; it's much worse than the map.
extension Array {
func unsafeCastToArrayOf<T>(type: T.Type) -> [T] {
return map{$0 as! T}
}
}
let prods: [ProductType] = milks.unsafeCastToArrayOf(ProductType)
// Anything better?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment