On Jun 29, 2016, at 8:47 AM, Matthew Johnson <[email protected]> wrote:
> 
> On Jun 29, 2016, at 7:52 AM, David Sweeris via swift-evolution 
> <[email protected] <mailto:[email protected]>> wrote:
> 
>> Aside from confusing people, does it actually hurt anything? It's not too 
>> hard to imagine that someone might make a type conform to `Boolean` because, 
>> within their code, the semantics of "x || y” are clear and that reads better 
>> than "x.foo || y.foo".
>> 
>> I agree it feels out of place, though. What about renaming it to something 
>> like "CustomBooleanConvertible”?
> 
> IIRC Optional conformed to this protocol early on and that conformance was 
> removed.  In practice the idea of a protocol for "truthiness" to which 
> non-Boolean types conform caused more confusion than it provided value.  It 
> was a cool idea that just didn't work out so well.
> 
> IMO if it doesn't make sense for Optional to conform it is pretty unlikely it 
> would make sense for other types to conform.  It seems like a good idea to 
> remove the protocol.

What if you wanted to do something like this?
class RemoteBool : Boolean {
    let url: URL
    private var cachedValue: Bool? = nil // gets updated periodically in 
another thread or some other async method
    init(boolURL: URL) { url = boolURL; sync_update() }
    var boolValue: Bool { return cachedValue ?? sync_update() }
    func sync_update() -> Bool {…} // synchronously sets `cachedValue` and 
returns the newValue
    func async_update() {…} // asynchronously sets `cachedValue`
}

Or experiment with how ternary logic interacts with boolean logic?
protocol Ternary : Boolean, BooleanLiteralConvertible, NilLiteralConvertible {
    static var forcedBoolValue: Bool { get }
    var ternValue: Bool? { get set }
    init(_: Bool?)
}
extension Ternary {
    var boolValue: Bool { return ternValue ?? Self.forcedBoolValue }
    init(booleanLiteral value: Bool) { self.init(value) }
    init(nilLiteral: ()) { self.init(nil) }
}
struct TendsTrue: Ternary {
    static let forcedBoolValue = true
    var ternValue: Bool?
    init(_ value: Bool?) { ternValue = value }
}
struct TendsFalse: Ternary {
    static let forcedBoolValue = false
    var ternValue: Bool?
    init(_ value: Bool?) { ternValue = value }
}

Yeah, sure, in either case you could go through and use extensions to add 
support for your custom type on an as-needed basis. Life would be way easier, 
though, if the standard library was simply coded to an abstracted boolean 
protocol. Isn’t this kind of scenario that led to Swift having generics?

Renaming `Boolean` to something that doesn’t sort next to `Bool` removes the 
source of confusion. And while I completely agree that the standard library 
should be consistent it its use of abstraction protocols vs concrete types, in 
this regard I think this proposal goes in the wrong direction (although, in my 
whatever-the-opposite-of-defense-is I’m a huge fan of having generic library 
code wherever possible, so maybe I’m biased).

Is there a downside to overloading any function which takes a Bool with a 
version that takes a “CustomBooleanConvertible”?
func foo(_ bar: Bool) {} // pretend this exists in the standard library
func foo <T: CustomBooleanConvertible> (_ bar: T) { foo(bar.boolValue) } // add 
this, and keep the concrete version as well, both to provide the actual 
implementation and to prevent the generic version from recursively calling 
itself

- Dave Sweeris
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to