Either protocol syntax


(Rex) #1

Hello, I believe there was some discussion about this quite awhile ago. I
was wondering if there's any interest in including a protocol 'or' type
that would be the intersection of two protocols. This could be really
useful in situations where a framework that the user has no control over
implements a portion of some often used protocol. Such as specialized
collections from an Database framework that don't implement
RangeReplaceableCollection but have a set of methods that are equivalent.
The user can then implement a protocol that is the intersection of those
set of methods and not duplicate code.

Simplified example:

protocol Animal {
    var hasEars: Bool { get }
    func grow()
}

protocol Plant {
    var isGreen: Bool { get }
    func grow()
}

protocol LivingThing = Plant | Animal // or a different syntax

LivingThing's is as follows
{
    func grow()
}

···

--

Rex Fenley | IOS DEVELOPER

Remind.com <https://www.remind.com/> | BLOG <http://blog.remind.com/>
> FOLLOW
US <https://twitter.com/remindhq> | LIKE US
<https://www.facebook.com/remindhq>


(Matthew Johnson) #2

Hello, I believe there was some discussion about this quite awhile ago. I was wondering if there's any interest in including a protocol 'or' type that would be the intersection of two protocols. This could be really useful in situations where a framework that the user has no control over implements a portion of some often used protocol. Such as specialized collections from an Database framework that don't implement RangeReplaceableCollection but have a set of methods that are equivalent. The user can then implement a protocol that is the intersection of those set of methods and not duplicate code.

If the specialized collection in the database framework already provides functionality equivalent to `RangeReplaceableCollection` what you really want to do is just provide the conformance you’re looking for in an extension:

extension SpecializedDatabaseCollection: RangeReplaceableCollection {
   // if necessary, provide forwarding wrappers where the member names don’t match up.
}

But in a case like this the framework itself really should provide this conformance out of the box. If they didn’t, maybe there is a good reason so you would want to find out why it wasn’t provided.

Is there something you’re hoping to do that you can’t solve by simply extending the framework types?

···

On Feb 2, 2017, at 3:26 PM, Rex Fenley via swift-evolution <swift-evolution@swift.org> wrote:

Simplified example:

protocol Animal {
    var hasEars: Bool { get }
    func grow()
}

protocol Plant {
    var isGreen: Bool { get }
    func grow()
}

protocol LivingThing = Plant | Animal // or a different syntax

LivingThing's is as follows
{
    func grow()
}

--
Rex Fenley | IOS DEVELOPER

Remind.com <https://www.remind.com/> | BLOG <http://blog.remind.com/> | FOLLOW US <https://twitter.com/remindhq> | LIKE US <https://www.facebook.com/remindhq>_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Adrian Zubarev) #3

Look for Disjunctions (logical ORs) in type constraints. :wink:

It’s rejected.

···

--
Adrian Zubarev
Sent with Airmail

Am 2. Februar 2017 um 22:26:44, Rex Fenley via swift-evolution (swift-evolution@swift.org) schrieb:

Hello, I believe there was some discussion about this quite awhile ago. I was wondering if there's any interest in including a protocol 'or' type that would be the intersection of two protocols. This could be really useful in situations where a framework that the user has no control over implements a portion of some often used protocol. Such as specialized collections from an Database framework that don't implement RangeReplaceableCollection but have a set of methods that are equivalent. The user can then implement a protocol that is the intersection of those set of methods and not duplicate code.

Simplified example:

protocol Animal {
var hasEars: Bool { get }
func grow()
}

protocol Plant {
var isGreen: Bool { get }
func grow()
}

protocol LivingThing = Plant | Animal // or a different syntax

LivingThing's is as follows
{
func grow()
}

--

Rex Fenley
>
IOS
DEVELOPER

Remind.com

BLOG

> FOLLOW
US
>
LIKE US
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Anton Zhilin) #4

As a side note, some people want inline enum types with exact syntax of A|B.
The difference is that in this case the chosen side of inline enum is
always meaningful. That is, if S:A&B and x:S, then .0(x) as A|B ≠ .1(x) as
A>B
I guess, the version suggested by TS reflects what Chris considered
harmful. Those inline enums may be more feasible.


(Rex) #5

My use case is RLMArray and it can't implement
RangeReplaceableCollection though
because `init` is unavailable, additionally, there's a lot of parts to the
protocol that would take some time to implement correctly if I could. They
offer a Swift type List that wraps RLMArray and does a bunch of stuff to
implement RangeReplaceableCollection, but they discourage using their Swift
library in mixed Obj-C/Swift projects and certain model objects simply
couldn't use the List type anyway because they're also used in Obj-C and
List is not @objc compliant.

So this leaves me in situations where when I need to use Array or RLMArray
I have to duplicate my code, not just in one place, but all the way down a
pipeline in order to have my generics work with either
RangeReplaceableCollection
or RLMArray.

If I could abstract the commonalities required by my application, I could
just have a RLMArrayProtocol that has RLMArray's exposed function
signatures and a new protocol Appendable = RangeReplaceableCollection

RLMArrayProtocol

and this will type check all the way through the pipeline.

tl;dr - if a function signature required by a protocol is marked
unavailable on a class, then disjunction is necessary in order to bridge
the two (or more) types without duplicating code.

···

On Thu, Feb 2, 2017 at 1:35 PM, Matthew Johnson <matthew@anandabits.com> wrote:

On Feb 2, 2017, at 3:26 PM, Rex Fenley via swift-evolution < > swift-evolution@swift.org> wrote:

Hello, I believe there was some discussion about this quite awhile ago. I
was wondering if there's any interest in including a protocol 'or' type
that would be the intersection of two protocols. This could be really
useful in situations where a framework that the user has no control over
implements a portion of some often used protocol. Such as specialized
collections from an Database framework that don't implement
RangeReplaceableCollection but have a set of methods that are equivalent.
The user can then implement a protocol that is the intersection of those
set of methods and not duplicate code.

If the specialized collection in the database framework already provides
functionality equivalent to `RangeReplaceableCollection` what you really
want to do is just provide the conformance you’re looking for in an
extension:

extension SpecializedDatabaseCollection: RangeReplaceableCollection {
   // if necessary, provide forwarding wrappers where the member names
don’t match up.
}

But in a case like this the framework itself really should provide this
conformance out of the box. If they didn’t, maybe there is a good reason
so you would want to find out why it wasn’t provided.

Is there something you’re hoping to do that you can’t solve by simply
extending the framework types?

Simplified example:

protocol Animal {
    var hasEars: Bool { get }
    func grow()
}

protocol Plant {
    var isGreen: Bool { get }
    func grow()
}

protocol LivingThing = Plant | Animal // or a different syntax

LivingThing's is as follows
{
    func grow()
}

--
Rex Fenley | IOS DEVELOPER

Remind.com <https://www.remind.com/> | BLOG <http://blog.remind.com/> |
FOLLOW US <https://twitter.com/remindhq> | LIKE US
<https://www.facebook.com/remindhq>
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

--

Rex Fenley | IOS DEVELOPER

Remind.com <https://www.remind.com/> | BLOG <http://blog.remind.com/>
> FOLLOW
US <https://twitter.com/remindhq> | LIKE US
<https://www.facebook.com/remindhq>


(Matthew Johnson) #6

My use case is RLMArray and it can't implement RangeReplaceableCollection though because `init` is unavailable, additionally, there's a lot of parts to the protocol that would take some time to implement correctly if I could. They offer a Swift type List that wraps RLMArray and does a bunch of stuff to implement RangeReplaceableCollection, but they discourage using their Swift library in mixed Obj-C/Swift projects and certain model objects simply couldn't use the List type anyway because they're also used in Obj-C and List is not @objc compliant.

So this leaves me in situations where when I need to use Array or RLMArray I have to duplicate my code, not just in one place, but all the way down a pipeline in order to have my generics work with either RangeReplaceableCollection or RLMArray.

If I could abstract the commonalities required by my application, I could just have a RLMArrayProtocol that has RLMArray's exposed function signatures and a new protocol Appendable = RangeReplaceableCollection | RLMArrayProtocol and this will type check all the way through the pipeline.

tl;dr - if a function signature required by a protocol is marked unavailable on a class, then disjunction is necessary in order to bridge the two (or more) types without duplicating code.

You should be able to solve this problem today by creating a custom protocol that you use as a constraint in your generic code and providing conformances for both Array and RLMArray.

···

On Feb 2, 2017, at 3:46 PM, Rex Fenley <rex@remind101.com> wrote:

On Thu, Feb 2, 2017 at 1:35 PM, Matthew Johnson <matthew@anandabits.com <mailto:matthew@anandabits.com>> wrote:

On Feb 2, 2017, at 3:26 PM, Rex Fenley via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hello, I believe there was some discussion about this quite awhile ago. I was wondering if there's any interest in including a protocol 'or' type that would be the intersection of two protocols. This could be really useful in situations where a framework that the user has no control over implements a portion of some often used protocol. Such as specialized collections from an Database framework that don't implement RangeReplaceableCollection but have a set of methods that are equivalent. The user can then implement a protocol that is the intersection of those set of methods and not duplicate code.

If the specialized collection in the database framework already provides functionality equivalent to `RangeReplaceableCollection` what you really want to do is just provide the conformance you’re looking for in an extension:

extension SpecializedDatabaseCollection: RangeReplaceableCollection {
   // if necessary, provide forwarding wrappers where the member names don’t match up.
}

But in a case like this the framework itself really should provide this conformance out of the box. If they didn’t, maybe there is a good reason so you would want to find out why it wasn’t provided.

Is there something you’re hoping to do that you can’t solve by simply extending the framework types?

Simplified example:

protocol Animal {
    var hasEars: Bool { get }
    func grow()
}

protocol Plant {
    var isGreen: Bool { get }
    func grow()
}

protocol LivingThing = Plant | Animal // or a different syntax

LivingThing's is as follows
{
    func grow()
}

--
Rex Fenley | IOS DEVELOPER

Remind.com <https://www.remind.com/> | BLOG <http://blog.remind.com/> | FOLLOW US <https://twitter.com/remindhq> | LIKE US <https://www.facebook.com/remindhq>_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

--
Rex Fenley | IOS DEVELOPER

Remind.com <https://www.remind.com/> | BLOG <http://blog.remind.com/> | FOLLOW US <https://twitter.com/remindhq> | LIKE US <https://www.facebook.com/remindhq>


(Rex) #7

But then any time as user of the pipeline I'm writing would like a new type
of collection they will be forced to inherit this new protocol vs one
they're already familiar with and which the collection may already conform
too.

···

On Thu, Feb 2, 2017 at 1:53 PM, Matthew Johnson <matthew@anandabits.com> wrote:

On Feb 2, 2017, at 3:46 PM, Rex Fenley <rex@remind101.com> wrote:

My use case is RLMArray and it can't implement RangeReplaceableCollection though
because `init` is unavailable, additionally, there's a lot of parts to the
protocol that would take some time to implement correctly if I could. They
offer a Swift type List that wraps RLMArray and does a bunch of stuff to
implement RangeReplaceableCollection, but they discourage using their
Swift library in mixed Obj-C/Swift projects and certain model objects
simply couldn't use the List type anyway because they're also used in Obj-C
and List is not @objc compliant.

So this leaves me in situations where when I need to use Array or RLMArray
I have to duplicate my code, not just in one place, but all the way down a
pipeline in order to have my generics work with either
RangeReplaceableCollection or RLMArray.

If I could abstract the commonalities required by my application, I could
just have a RLMArrayProtocol that has RLMArray's exposed function
signatures and a new protocol Appendable = RangeReplaceableCollection | RLMArrayProtocol
and this will type check all the way through the pipeline.

tl;dr - if a function signature required by a protocol is marked
unavailable on a class, then disjunction is necessary in order to bridge
the two (or more) types without duplicating code.

You should be able to solve this problem today by creating a custom
protocol that you use as a constraint in your generic code and providing
conformances for both Array and RLMArray.

On Thu, Feb 2, 2017 at 1:35 PM, Matthew Johnson <matthew@anandabits.com> > wrote:

On Feb 2, 2017, at 3:26 PM, Rex Fenley via swift-evolution < >> swift-evolution@swift.org> wrote:

Hello, I believe there was some discussion about this quite awhile ago. I
was wondering if there's any interest in including a protocol 'or' type
that would be the intersection of two protocols. This could be really
useful in situations where a framework that the user has no control over
implements a portion of some often used protocol. Such as specialized
collections from an Database framework that don't implement
RangeReplaceableCollection but have a set of methods that are equivalent.
The user can then implement a protocol that is the intersection of those
set of methods and not duplicate code.

If the specialized collection in the database framework already provides
functionality equivalent to `RangeReplaceableCollection` what you really
want to do is just provide the conformance you’re looking for in an
extension:

extension SpecializedDatabaseCollection: RangeReplaceableCollection {
   // if necessary, provide forwarding wrappers where the member names
don’t match up.
}

But in a case like this the framework itself really should provide this
conformance out of the box. If they didn’t, maybe there is a good reason
so you would want to find out why it wasn’t provided.

Is there something you’re hoping to do that you can’t solve by simply
extending the framework types?

Simplified example:

protocol Animal {
    var hasEars: Bool { get }
    func grow()
}

protocol Plant {
    var isGreen: Bool { get }
    func grow()
}

protocol LivingThing = Plant | Animal // or a different syntax

LivingThing's is as follows
{
    func grow()
}

--
Rex Fenley | IOS DEVELOPER

Remind.com <https://www.remind.com/> | BLOG <http://blog.remind.com/>
> FOLLOW US <https://twitter.com/remindhq> | LIKE US
<https://www.facebook.com/remindhq>
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

--
Rex Fenley | IOS DEVELOPER

Remind.com <https://www.remind.com/> | BLOG <http://blog.remind.com/> |
FOLLOW US <https://twitter.com/remindhq> | LIKE US
<https://www.facebook.com/remindhq>

--

Rex Fenley | IOS DEVELOPER

Remind.com <https://www.remind.com/> | BLOG <http://blog.remind.com/>
> FOLLOW
US <https://twitter.com/remindhq> | LIKE US
<https://www.facebook.com/remindhq>


(Matthew Johnson) #8

But then any time as user of the pipeline I'm writing would like a new type of collection they will be forced to inherit this new protocol vs one they're already familiar with and which the collection may already conform too.

Yes, that is true. But if you design your new protocol such that it’s requirements all match a requirement in `RangeReplaceableCollection` then conformance will be a one-line extension. This may not be ideal, but it’s really not too bad and you can do it today.

···

On Feb 2, 2017, at 4:02 PM, Rex Fenley <rex@remind101.com> wrote:

On Thu, Feb 2, 2017 at 1:53 PM, Matthew Johnson <matthew@anandabits.com <mailto:matthew@anandabits.com>> wrote:

On Feb 2, 2017, at 3:46 PM, Rex Fenley <rex@remind101.com <mailto:rex@remind101.com>> wrote:

My use case is RLMArray and it can't implement RangeReplaceableCollection though because `init` is unavailable, additionally, there's a lot of parts to the protocol that would take some time to implement correctly if I could. They offer a Swift type List that wraps RLMArray and does a bunch of stuff to implement RangeReplaceableCollection, but they discourage using their Swift library in mixed Obj-C/Swift projects and certain model objects simply couldn't use the List type anyway because they're also used in Obj-C and List is not @objc compliant.

So this leaves me in situations where when I need to use Array or RLMArray I have to duplicate my code, not just in one place, but all the way down a pipeline in order to have my generics work with either RangeReplaceableCollection or RLMArray.

If I could abstract the commonalities required by my application, I could just have a RLMArrayProtocol that has RLMArray's exposed function signatures and a new protocol Appendable = RangeReplaceableCollection | RLMArrayProtocol and this will type check all the way through the pipeline.

tl;dr - if a function signature required by a protocol is marked unavailable on a class, then disjunction is necessary in order to bridge the two (or more) types without duplicating code.

You should be able to solve this problem today by creating a custom protocol that you use as a constraint in your generic code and providing conformances for both Array and RLMArray.

On Thu, Feb 2, 2017 at 1:35 PM, Matthew Johnson <matthew@anandabits.com <mailto:matthew@anandabits.com>> wrote:

On Feb 2, 2017, at 3:26 PM, Rex Fenley via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hello, I believe there was some discussion about this quite awhile ago. I was wondering if there's any interest in including a protocol 'or' type that would be the intersection of two protocols. This could be really useful in situations where a framework that the user has no control over implements a portion of some often used protocol. Such as specialized collections from an Database framework that don't implement RangeReplaceableCollection but have a set of methods that are equivalent. The user can then implement a protocol that is the intersection of those set of methods and not duplicate code.

If the specialized collection in the database framework already provides functionality equivalent to `RangeReplaceableCollection` what you really want to do is just provide the conformance you’re looking for in an extension:

extension SpecializedDatabaseCollection: RangeReplaceableCollection {
   // if necessary, provide forwarding wrappers where the member names don’t match up.
}

But in a case like this the framework itself really should provide this conformance out of the box. If they didn’t, maybe there is a good reason so you would want to find out why it wasn’t provided.

Is there something you’re hoping to do that you can’t solve by simply extending the framework types?

Simplified example:

protocol Animal {
    var hasEars: Bool { get }
    func grow()
}

protocol Plant {
    var isGreen: Bool { get }
    func grow()
}

protocol LivingThing = Plant | Animal // or a different syntax

LivingThing's is as follows
{
    func grow()
}

--
Rex Fenley | IOS DEVELOPER

Remind.com <https://www.remind.com/> | BLOG <http://blog.remind.com/> | FOLLOW US <https://twitter.com/remindhq> | LIKE US <https://www.facebook.com/remindhq>_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

--
Rex Fenley | IOS DEVELOPER

Remind.com <https://www.remind.com/> | BLOG <http://blog.remind.com/> | FOLLOW US <https://twitter.com/remindhq> | LIKE US <https://www.facebook.com/remindhq>

--
Rex Fenley | IOS DEVELOPER

Remind.com <https://www.remind.com/> | BLOG <http://blog.remind.com/> | FOLLOW US <https://twitter.com/remindhq> | LIKE US <https://www.facebook.com/remindhq>


(Robert Widmann) #9

It sounds like what you want is an GADT-like adaptor gadget to try to bridge between these protocols across these specific types. With general disjuncts you’re subject to the open world assumption - that anybody that should conform to a (visible) protocol, can conform to that protocol - thus rendering any attempts to inspect the kind of thing you’ve got in the disjunct useless.

~Robert Widmann

···

On Feb 2, 2017, at 5:02 PM, Rex Fenley via swift-evolution <swift-evolution@swift.org> wrote:

But then any time as user of the pipeline I'm writing would like a new type of collection they will be forced to inherit this new protocol vs one they're already familiar with and which the collection may already conform too.

On Thu, Feb 2, 2017 at 1:53 PM, Matthew Johnson <matthew@anandabits.com <mailto:matthew@anandabits.com>> wrote:

On Feb 2, 2017, at 3:46 PM, Rex Fenley <rex@remind101.com <mailto:rex@remind101.com>> wrote:

My use case is RLMArray and it can't implement RangeReplaceableCollection though because `init` is unavailable, additionally, there's a lot of parts to the protocol that would take some time to implement correctly if I could. They offer a Swift type List that wraps RLMArray and does a bunch of stuff to implement RangeReplaceableCollection, but they discourage using their Swift library in mixed Obj-C/Swift projects and certain model objects simply couldn't use the List type anyway because they're also used in Obj-C and List is not @objc compliant.

So this leaves me in situations where when I need to use Array or RLMArray I have to duplicate my code, not just in one place, but all the way down a pipeline in order to have my generics work with either RangeReplaceableCollection or RLMArray.

If I could abstract the commonalities required by my application, I could just have a RLMArrayProtocol that has RLMArray's exposed function signatures and a new protocol Appendable = RangeReplaceableCollection | RLMArrayProtocol and this will type check all the way through the pipeline.

tl;dr - if a function signature required by a protocol is marked unavailable on a class, then disjunction is necessary in order to bridge the two (or more) types without duplicating code.

You should be able to solve this problem today by creating a custom protocol that you use as a constraint in your generic code and providing conformances for both Array and RLMArray.

On Thu, Feb 2, 2017 at 1:35 PM, Matthew Johnson <matthew@anandabits.com <mailto:matthew@anandabits.com>>wrote:

On Feb 2, 2017, at 3:26 PM, Rex Fenley via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hello, I believe there was some discussion about this quite awhile ago. I was wondering if there's any interest in including a protocol 'or' type that would be the intersection of two protocols. This could be really useful in situations where a framework that the user has no control over implements a portion of some often used protocol. Such as specialized collections from an Database framework that don't implement RangeReplaceableCollection but have a set of methods that are equivalent. The user can then implement a protocol that is the intersection of those set of methods and not duplicate code.

If the specialized collection in the database framework already provides functionality equivalent to `RangeReplaceableCollection` what you really want to do is just provide the conformance you’re looking for in an extension:

extension SpecializedDatabaseCollection: RangeReplaceableCollection {
   // if necessary, provide forwarding wrappers where the member names don’t match up.
}

But in a case like this the framework itself really should provide this conformance out of the box. If they didn’t, maybe there is a good reason so you would want to find out why it wasn’t provided.

Is there something you’re hoping to do that you can’t solve by simply extending the framework types?

Simplified example:

protocol Animal {
    var hasEars: Bool { get }
    func grow()
}

protocol Plant {
    var isGreen: Bool { get }
    func grow()
}

protocol LivingThing = Plant | Animal // or a different syntax

LivingThing's is as follows
{
    func grow()
}

--
Rex Fenley | IOS DEVELOPER

Remind.com <https://www.remind.com/> | BLOG <http://blog.remind.com/> | FOLLOW US <https://twitter.com/remindhq> | LIKE US <https://www.facebook.com/remindhq>_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

--
Rex Fenley | IOS DEVELOPER

Remind.com <https://www.remind.com/> | BLOG <http://blog.remind.com/> | FOLLOW US <https://twitter.com/remindhq> | LIKE US <https://www.facebook.com/remindhq>

--
Rex Fenley | IOS DEVELOPER

Remind.com <https://www.remind.com/> | BLOG <http://blog.remind.com/> | FOLLOW US <https://twitter.com/remindhq> | LIKE US <https://www.facebook.com/remindhq>_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution