Below is my attempt to write a protocol called StringInitializable and make some types conform to it.
Any type T conforming to the protocol can be initialized like this:
let x = T("...")
where "..." is a string representation for a value of type T. It returns an Optional<T> which will be nil if the string is not a valid string representation.
As the code shows, it's easy (and boilerplaty) enough to make eg the basic number types and bool conform, but I'm stuck on how to make Array conform.
So, how to make Array (or better yet, CollectionType) conform to StringInitializable?
Thanks!
(Swift 2, Xcode 7 beta 6)
// Here's the simple protocol:
protocol StringInitializable {
init?(_ : String)
}
// Adding conformance for these types is easy:
extension Double : StringInitializable { }
extension Float : StringInitializable { }
extension Float80 : StringInitializable { }
extension Int : StringInitializable { init?(_ s : String) { self.init(s, radix: 10) } }
extension UInt : StringInitializable { init?(_ s : String) { self.init(s, radix: 10) } }
extension Int8 : StringInitializable { init?(_ s : String) { self.init(s, radix: 10) } }
extension UInt8 : StringInitializable { init?(_ s : String) { self.init(s, radix: 10) } }
extension Int16 : StringInitializable { init?(_ s : String) { self.init(s, radix: 10) } }
extension UInt16 : StringInitializable { init?(_ s : String) { self.init(s, radix: 10) } }
extension Int32 : StringInitializable { init?(_ s : String) { self.init(s, radix: 10) } }
extension UInt32 : StringInitializable { init?(_ s : String) { self.init(s, radix: 10) } }
extension Int64 : StringInitializable { init?(_ s : String) { self.init(s, radix: 10) } }
extension UInt64 : StringInitializable { init?(_ s : String) { self.init(s, radix: 10) } }
extension Bool : StringInitializable {
init?(_ s : String) {
switch s {
case "true" : self.init(true)
case "false" : self.init(false)
default: return nil
}
}
}
// But here's my failed attempt at Array:
extension Array : StringInitializable {
init?(_ s : String) {
let whiteSpaceRemoved = String(s.characters.filter { !" \t\n\r".characters.contains($0) })
let bracketsRemoved = String(whiteSpaceRemoved.characters.dropFirst().dropLast())
let arrayOfStrings = bracketsRemoved.characters.split(",").map { String($0) }
print(arrayOfStrings) // Prints eg ["1", "2", "3"]
// This won't work:
// let arrayOfOptionals = arrayOfStrings.map { Element.init($0) }
return nil // I'll just return nil for now ... : (
}
}
// Example usage for arrays:
let ok = [Int]("[1, 2, 3]")
print(ok) // Should print [1, 2, 3]
let meh = [Int]("[1, 2.0, 3]")
print(meh) // Should print nil(The program can be run as is, but Array is obviously not conforming properly to the protocol. It would be nice if only Arrays whose Element conforms to StringInitializable would conform, but it's ok if all Arrays conform and those whose Element does not conform just becomes nil.)