> On 20 Feb 2017, at 00:15, Brent Royal-Gordon via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
>> On Feb 18, 2017, at 10:58 PM, David Waite via swift-evolution 
>> <swift-evolution@swift.org> wrote:
>> 
>> I am unsure if this feature is a good idea. Does someone have a real-world 
>> use for this which isn’t just hiding strong implementation coupling behind a 
>> protocol?
> 
> Strong coupling is sometimes inevitable.
> 
> In a previous thread, I brought up an example of a place I would use this 
> feature: Wrapping the SQLite APIs. For instance:
> 
>       public protocol SQLiteValue {
>               init(statement: SQLiteStatement, columnAt index: Int) throws
>               func bind(to statement: SQLiteStatement, at index: Int) throws
>       }
>       extension Int: SQLiteValue {
>               public init(statement: SQLiteStatement, columnAt index: Int) 
> throws {
>                       self = sqlite3_column_int(statement.stmt, index)
>               }
>               public func bind(to statement: SQLiteStatement, at index: Int) 
> throws {
>                       try throwIfNotOK(
>                               sqlite3_bind_int64(statement.stmt, index, self)
>                       )
>               }
>       }
>       extension Double: SQLiteValue {…}
>       extension Data: SQLiteValue {…}
>       extension String: SQLiteValue {…}
>       extension Optional: SQLiteValue where Wrapped: SQLiteValue {…}

That problem is that I don’t think the API should be written this way. This 
cries for the use of enums instead:

enum SQLiteValue {
    case int(Int)
    case double(Double)
    case data(Data)
    case string(String)
}

protocol SQLiteValueConvertible {
    var sqliteValue: SQLiteValue { get }
}

extension Int : SQLiteValueConvertible {
    var sqliteValue: SQLiteValue { return .int(self) }
}

And that API actually allows interesting extension points. For example, how 
about automatic binding of dates:

extension Date : SQLiteValueConvertible {
    var sqliteValue: SQLiteValue { return .double(timeIntervalSince1970) }
}

I keep getting the impression that the uses for the proposals are actually 
cases where an enum is required.

> This is a case of your hated "strong implementation coupling". But the 
> coupling is to a library that ultimately writes data to disk in a portable 
> format. Strong coupling here is inevitable.
> 
> What is the purpose of permitting outside conformances to `SQLiteValue`? 
> There is no useful way to conform to `SQLiteValue`; the underlying library 
> supports certain types, and I've implemented support for those types. 
> Allowing outside conformances can only mislead people into fruitlessly trying 
> to conform their types, not realizing that the calls they need simply aren't 
> exposed.
> 
> Moreover, exposing these details unnecessarily freezes the design of 
> `SQLiteValue`. If I want to change the design of this parameter handling in a 
> future version, well, too bad, the API is public, I'm stuck. *For an API I 
> don't intend anyone to conform to publicly in the first place.* That kind of 
> sucks, doesn't it?
> 
> -- 
> Brent Royal-Gordon
> Architechies
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to