Specify type of a delegate which conforms to a protocol


(Inder Kumar Rathore) #1

Hi All,
I used to do this in Obj-C but I'm unable to do this in swift

*UIViewController<MyProtocol> *delegate;*

I posted this question on dev forums but didn't get the solution and
finally I'm reporting here so that It can be added as a features in the
coming releases.

Thanks

Rathore


(David Sweeris) #2

That might solve Inder’s problem, but strictly speaking it doesn’t actually restrict the type to an enum. This struct meets all of RawRepresentable’s requirements:
struct Foo : RawRepresentable {
    typealias RawValue = String
    init?(rawValue: Foo.RawValue) {
        return nil
    }
    var rawValue: RawValue = "bar"
}

(Although in practice I can’t think of why that would matter, since you can’t do anything with a RawRepresentable other than get it’s rawValue or call init?(rawValue: String), and neither of those rely on enum features… I’ll stop being pedantic now.)

Anyway, the bigger point is that there’s no way to restrict a generic type to be an enum. I think it’s because there wouldn’t be a way to switch on it (or do other enum-ish things) without knowing all its cases, which requires knowing exactly which type it is, which means it’s no longer a generic type. That’s just a guess, though.

Maybe someone should propose that we allow something like this:
func foobar <T, U where T: (case .foo, case .bar)> (value: T) -> U {
    switch value {
    case .foo: ...
    case .bar: ...
    }
}

- Dave Sweeris

···

On Feb 9, 2016, at 10:47, Alex Hoppen via swift-evolution <swift-evolution@swift.org> wrote:

As for a new syntax, I was also thinking about this issue a few days ago and it occurred to me that there are even more types that cannot be properly represented in Swift. For example there is currently no way (that I know of) to create a variable that can contain any enum that is backed by a String. However, these kinds of constraints can easily be specified in generic constraints (the ones in angle brackets). Maybe we could add the same syntax for variables/constants as well so that the code would look something like the following for your issue:

var<T, where T: UIViewController, T: MyProtocol> myVar: T

or for enums backed by a String:

var<T: RawRepresentable where T.RawValue == String> myVar: T

Tell me what you think about it.

- Alex

On 09 Feb 2016, at 15:58, Inder Kumar Rathore . via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hi All,
I used to do this in Obj-C but I'm unable to do this in swift

UIViewController<MyProtocol> *delegate;

I posted this question on dev forums but didn't get the solution and finally I'm reporting here so that It can be added as a features in the coming releases.

Thanks

Rathore
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto: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


(Alex Hoppen) #3

At the moment you can achieve the same effect using the following construction (at least that’s what I used):

protocol UIViewControllerProtocol {} // Make sure only UIViewController conforms to this protocol

extension UIViewController: UIViewControllerProtocol {}

protocol MyProtocol {}

let myVar: protocol<UIViewControllerProtocol, MyProtocol>

It’s obviously far longer and less obvious but I hope it at least solves your issue for now.

- Alex

···

On 09 Feb 2016, at 15:58, Inder Kumar Rathore . via swift-evolution <swift-evolution@swift.org> wrote:

Hi All,
I used to do this in Obj-C but I'm unable to do this in swift

UIViewController<MyProtocol> *delegate;

I posted this question on dev forums but didn't get the solution and finally I'm reporting here so that It can be added as a features in the coming releases.

Thanks

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


(Alex Hoppen) #4

As for a new syntax, I was also thinking about this issue a few days ago and it occurred to me that there are even more types that cannot be properly represented in Swift. For example there is currently no way (that I know of) to create a variable that can contain any enum that is backed by a String. However, these kinds of constraints can easily be specified in generic constraints (the ones in angle brackets). Maybe we could add the same syntax for variables/constants as well so that the code would look something like the following for your issue:

var<T, where T: UIViewController, T: MyProtocol> myVar: T

or for enums backed by a String:

var<T: RawRepresentable where T.RawValue == String> myVar: T

Tell me what you think about it.

- Alex

···

On 09 Feb 2016, at 15:58, Inder Kumar Rathore . via swift-evolution <swift-evolution@swift.org> wrote:

Hi All,
I used to do this in Obj-C but I'm unable to do this in swift

UIViewController<MyProtocol> *delegate;

I posted this question on dev forums but didn't get the solution and finally I'm reporting here so that It can be added as a features in the coming releases.

Thanks

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


(Alex Hoppen) #5

That might solve Inder’s problem, but strictly speaking it doesn’t actually restrict the type to an enum. This struct meets all of RawRepresentable’s requirements:
struct Foo : RawRepresentable {
    typealias RawValue = String
    init?(rawValue: Foo.RawValue) {
        return nil
    }
    var rawValue: RawValue = "bar"
}

(Although in practice I can’t think of why that would matter, since you can’t do anything with a RawRepresentable other than get it’s rawValue or call init?(rawValue: String), and neither of those rely on enum features… I’ll stop being pedantic now.)

OK, your right, maybe my example was badly chosen. RawRepresentable was the first protocol with an associated type that came into my mind. But the same issue applies for a number of protocols as well, e.g. ArrayLiteralConvertible with associated value Element. Apart from the fact that I don’t like not being able to specify all variable types, you may want to use this in practice to store the values of an Array literal and decide later in what kind of data structure you would like to use to hold the values in the long term.

Anyway, the bigger point is that there’s no way to restrict a generic type to be an enum. I think it’s because there wouldn’t be a way to switch on it (or do other enum-ish things) without knowing all its cases, which requires knowing exactly which type it is, which means it’s no longer a generic type. That’s just a guess, though.

Maybe someone should propose that we allow something like this:
func foobar <T, U where T: (case .foo, case .bar)> (value: T) -> U {
    switch value {
    case .foo: ...
    case .bar: ...
    }
}

If you specify all the cases your enum should have, you could just specify the enum as well. The list would have to be exhaustive anyway so that the compiler can check that all cases have been covered in a switch statement and I can’t think of any reason why it would be useful to have two enums with exactly the same cases.

···

On 09 Feb 2016, at 21:00, davesweeris@mac.com wrote:

- Dave Sweeris

On Feb 9, 2016, at 10:47, Alex Hoppen via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

As for a new syntax, I was also thinking about this issue a few days ago and it occurred to me that there are even more types that cannot be properly represented in Swift. For example there is currently no way (that I know of) to create a variable that can contain any enum that is backed by a String. However, these kinds of constraints can easily be specified in generic constraints (the ones in angle brackets). Maybe we could add the same syntax for variables/constants as well so that the code would look something like the following for your issue:

var<T, where T: UIViewController, T: MyProtocol> myVar: T

or for enums backed by a String:

var<T: RawRepresentable where T.RawValue == String> myVar: T

Tell me what you think about it.

- Alex

On 09 Feb 2016, at 15:58, Inder Kumar Rathore . via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hi All,
I used to do this in Obj-C but I'm unable to do this in swift

UIViewController<MyProtocol> *delegate;

I posted this question on dev forums but didn't get the solution and finally I'm reporting here so that It can be added as a features in the coming releases.

Thanks

Rathore
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

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


(Tino) #6

The way to declare conformance to multiple protocols always seemed odd to me:

- It looks like protocol is a generic class, but generics always have a fixed number of parameters
- By convention, all types have to start with uppercase (besides protocol, there is at least another exception: Restricting protocols to reference types via "class")

So, I definitely think there is room for improvement here… how about recycling the inheritance syntax?

let controller: (UIViewController, UITableViewDatasource)

I added the braces because it would be really when you add the question mark for an optional value; an alternative for this case would be

let controller: Optional<UIViewController, UITableViewDatasource>

Tino


(Alexey Demedetskiy) #7

As alternative to a protocol solution, you can use value type wrapper:

struct Delegate<T where T:UIViewController, T:UITableViewDelegate> {
    let value: T
}

class MyController : UIViewController, UITableViewDelegate {}
class WrongController : UIViewController {}

let delegate = Delegate(value: MyController())

// error: generic parameter 'T' could not be inferred
let delegate = Delegate(value: WrongController())

- Alexey Demedetskiy

···

Hi All,
I used to do this in Obj-C but I'm unable to do this in swift

*UIViewController<MyProtocol>*delegate;*

I posted this question on dev forums but didn't get the solution and
finally I'm reporting here so that It can be added as a features in the
coming releases.

Thanks

Rathore


(David Sweeris) #8

That might solve Inder’s problem, but strictly speaking it doesn’t actually restrict the type to an enum. This struct meets all of RawRepresentable’s requirements:
struct Foo : RawRepresentable {
    typealias RawValue = String
    init?(rawValue: Foo.RawValue) {
        return nil
    }
    var rawValue: RawValue = "bar"
}

(Although in practice I can’t think of why that would matter, since you can’t do anything with a RawRepresentable other than get it’s rawValue or call init?(rawValue: String), and neither of those rely on enum features… I’ll stop being pedantic now.)

OK, your right, maybe my example was badly chosen. RawRepresentable was the first protocol with an associated type that came into my mind. But the same issue applies for a number of protocols as well, e.g. ArrayLiteralConvertible with associated value Element. Apart from the fact that I don’t like not being able to specify all variable types, you may want to use this in practice to store the values of an Array literal and decide later in what kind of data structure you would like to use to hold the values in the long term.

Your example was not poorly chosen, I was just pointing out that Swift doesn't currently have a mechanism for explicitly restricting a generic type to *only* being an enum, in the way that you can say "T: class" and then T must be a class (which I think is used so that you know T has reference semantics).

Anyway, the bigger point is that there’s no way to restrict a generic type to be an enum. I think it’s because there wouldn’t be a way to switch on it (or do other enum-ish things) without knowing all its cases, which requires knowing exactly which type it is, which means it’s no longer a generic type. That’s just a guess, though.

Maybe someone should propose that we allow something like this:
func foobar <T, U where T: (case .foo, case .bar)> (value: T) -> U {
    switch value {
    case .foo: ...
    case .bar: ...
    }
}

If you specify all the cases your enum should have, you could just specify the enum as well. The list would have to be exhaustive anyway so that the compiler can check that all cases have been covered in a switch statement and I can’t think of any reason why it would be useful to have two enums with exactly the same cases.

Sorry, I was unclear... I meant T would be restricted to any enum that has *at least* a foo case and a bar case... There could be others, too. Speaking of which, there should have been a "default" in there to handle when "value" is one of T's potential other cases.

- Dave Sweeris.

···

On Feb 9, 2016, at 12:16, Alex Hoppen <alex@ateamer.de> wrote:

On 09 Feb 2016, at 21:00, davesweeris@mac.com wrote:

Sent from my iPhone


(Brent Royal-Gordon) #9

So, I definitely think there is room for improvement here… how about recycling the inheritance syntax?

let controller: (UIViewController, UITableViewDatasource)

This declares a tuple containing a UIViewController and a UITableViewDataSource.

I added the braces because it would be really when you add the question mark for an optional value; an alternative for this case would be

let controller: Optional<UIViewController, UITableViewDatasource>

This attempts to declare an optional with two generic types, which doesn't work because Optional only has one type parameter. (But other types, like Dictionary, *do* take two type parameters.)

Swift does already have a syntax for declaring that a type must conform to two (or more!) protocols:

  let controller: protocol<UITableViewDataSource, UITableViewDelegate>

I think this could probably be extended to support one class type as well, perhaps with a new name:

  let controller: all<UIViewController, UITableViewDataSource>

···

--
Brent Royal-Gordon
Architechies


(Jordan Rose) #10

We've been calling it "any" or "Any" (as in "any instance that is-a UIViewController and is-a UITableViewDataSource"), but I think this is the direction we've been talking about over here.

(Not that syntax bikeshedding can't still be useful.)

Jordan

···

On Feb 10, 2016, at 5:00 , Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

So, I definitely think there is room for improvement here… how about recycling the inheritance syntax?

let controller: (UIViewController, UITableViewDatasource)

This declares a tuple containing a UIViewController and a UITableViewDataSource.

I added the braces because it would be really when you add the question mark for an optional value; an alternative for this case would be

let controller: Optional<UIViewController, UITableViewDatasource>

This attempts to declare an optional with two generic types, which doesn't work because Optional only has one type parameter. (But other types, like Dictionary, *do* take two type parameters.)

Swift does already have a syntax for declaring that a type must conform to two (or more!) protocols:

  let controller: protocol<UITableViewDataSource, UITableViewDelegate>

I think this could probably be extended to support one class type as well, perhaps with a new name:

  let controller: all<UIViewController, UITableViewDataSource>


#11

In the thread "Partially constrained protocols" we have discussed a similar approach using where clauses:

        protocol<MyProtocol where Self: UIViewController>

- Maximilian

···

Am 10.02.2016 um 14:00 schrieb Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org>:

So, I definitely think there is room for improvement here… how about recycling the inheritance syntax?

let controller: (UIViewController, UITableViewDatasource)

This declares a tuple containing a UIViewController and a UITableViewDataSource.

I added the braces because it would be really when you add the question mark for an optional value; an alternative for this case would be

let controller: Optional<UIViewController, UITableViewDatasource>

This attempts to declare an optional with two generic types, which doesn't work because Optional only has one type parameter. (But other types, like Dictionary, *do* take two type parameters.)

Swift does already have a syntax for declaring that a type must conform to two (or more!) protocols:

   let controller: protocol<UITableViewDataSource, UITableViewDelegate>

I think this could probably be extended to support one class type as well, perhaps with a new name:

   let controller: all<UIViewController, UITableViewDataSource>

--
Brent Royal-Gordon
Architechies

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


(Tino) #12

So, I definitely think there is room for improvement here… how about recycling the inheritance syntax?

let controller: (UIViewController, UITableViewDatasource)

This declares a tuple containing a UIViewController and a UITableViewDataSource.

right, normal parenthesis are already used...

let controller: Optional<UIViewController, UITableViewDatasource>

This attempts to declare an optional with two generic types, which doesn't work because Optional only has one type parameter. (But other types, like Dictionary, *do* take two type parameters.)

true as well — seems I've been quite dozy when I outlined those colliding syntaxes :wink:

However, I don't like grouping using brackets; how about
let controller: Optional<UIViewController & UITableViewDatasource>

As we have inout, the ampersand should still be available — and it would fit nicely with "|" for sum types (although I have no idea wether algebraic data types will be considered in the future)

Tino


(Thorsten Seitz) #13

Jordan, I'm not sure if I understood you correctly, do you mean to use

    all<A, B> for intersection types (Ceylon's A & B), i.e. a type conforming to all listed types
    any<A, B> for union types (Ceylon's A | B), i.e. a type conforming to any of the listed types

That would be fine, too, I think, while a bit heavier than Ceylon's syntax (though I seem to remember from another thread that there was a problem with using Ceylon's syntax in Swift, though the reason escapes me at the moment).

-Thorsten

···

Am 10.02.2016 um 18:26 schrieb Jordan Rose via swift-evolution <swift-evolution@swift.org>:

On Feb 10, 2016, at 5:00 , Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

So, I definitely think there is room for improvement here… how about recycling the inheritance syntax?

let controller: (UIViewController, UITableViewDatasource)

This declares a tuple containing a UIViewController and a UITableViewDataSource.

I added the braces because it would be really when you add the question mark for an optional value; an alternative for this case would be

let controller: Optional<UIViewController, UITableViewDatasource>

This attempts to declare an optional with two generic types, which doesn't work because Optional only has one type parameter. (But other types, like Dictionary, *do* take two type parameters.)

Swift does already have a syntax for declaring that a type must conform to two (or more!) protocols:

   let controller: protocol<UITableViewDataSource, UITableViewDelegate>

I think this could probably be extended to support one class type as well, perhaps with a new name:

   let controller: all<UIViewController, UITableViewDataSource>

We've been calling it "any" or "Any" (as in "any instance that is-a UIViewController and is-a UITableViewDataSource"), but I think this is the direction we've been talking about over here.

(Not that syntax bikeshedding can't still be useful.)

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


(Inder Kumar Rathore) #14

I'm somewhat convinced with Maximilian

for

*protocol<MyProtocol where Self: UIViewController>*

Brent also has a valid point of having at least one class type in the
protocol

protocol<OneClass, OtherProtocol, SomeProtocol>

···

On Wed, Feb 10, 2016 at 10:56 PM, Jordan Rose via swift-evolution < swift-evolution@swift.org> wrote:

> On Feb 10, 2016, at 5:00 , Brent Royal-Gordon via swift-evolution < > swift-evolution@swift.org> wrote:
>
>> So, I definitely think there is room for improvement here… how about
recycling the inheritance syntax?
>>
>> let controller: (UIViewController, UITableViewDatasource)
>
> This declares a tuple containing a UIViewController and a
UITableViewDataSource.
>
>> I added the braces because it would be really when you add the question
mark for an optional value; an alternative for this case would be
>>
>> let controller: Optional<UIViewController, UITableViewDatasource>
>
> This attempts to declare an optional with two generic types, which
doesn't work because Optional only has one type parameter. (But other
types, like Dictionary, *do* take two type parameters.)
>
> Swift does already have a syntax for declaring that a type must conform
to two (or more!) protocols:
>
> let controller: protocol<UITableViewDataSource,
>
>
> I think this could probably be extended to support one class type as
well, perhaps with a new name:
>
> let controller: all<UIViewController, UITableViewDataSource>

We've been calling it "any" or "Any" (as in "any instance that is-a
UIViewController and is-a UITableViewDataSource"), but I think this is the
direction we've been talking about over here.

(Not that syntax bikeshedding can't still be useful.)

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

--
Best regards,
Inder Kumar Rathore


(Ross O'Brien) #15

I agree with everything Brent just said.
My question would then be: how does this extend?

Continuing the example:
'typealias ViewControllerTableViewDataSource = all<UIViewController,

'

It should then be possible to have a subtype of this which also conforms to
UITableViewDelegate.
So, given the above, this would work:
'typealias ViewControllerTableViewPackage = all<UIViewController,
UITableViewDataSource, UITableViewDelegate>'.
Would this also work?
'typealias ViewControllerTableViewPackage =
all<ViewControllerTableViewDataSource, UITableViewDelegate>'
Assuming someone defined this typealias: 'typealias TableViewPackage =
protocol<UITableViewDataSource, UITableViewDelegate>', would the above also
be equivalent to this?:
'typealias ViewControllerTableViewPackage = all<UIViewController,

'

The TableViewPackage protocol, defined above, is considered by Swift to be
a 'non-nominal type'. Thus this is illegal:
'extension TableViewPackage'
(I don't know why. Perhaps a type conforming to the separate protocols has
to opt-in to the combination?)

However, we can have the following:
'extension UITableViewDelegate where Self : UITableViewDataSource'
'extension UITableViewDelegate where Self : UIViewController'
'extension UITableViewDelegate where Self : UIViewController, Self :
UITableViewDataSource'

Similarly we can't currently have this:
'extension UIViewController where Self : UITableViewDataSource,
UITableViewDelegate'
because UIViewController is not a generic type (and this is part of the
original complaint).

It would be nice to be able to write this out as: 'extension
all<UIViewController, UITableViewDataSource, UITableViewDelegate>', even if
it's just syntactic sugar for 'extension UITableViewDelegate where Self :
UIViewController, Self : UITableViewDataSource'.

-- Ross

···

On Wed, Feb 10, 2016 at 1:44 PM, Maximilian Hünenberger < swift-evolution@swift.org> wrote:

In the thread "Partially constrained protocols" we have discussed a
similar approach using where clauses:

        protocol<MyProtocol where Self: UIViewController>

- Maximilian

Am 10.02.2016 um 14:00 schrieb Brent Royal-Gordon via swift-evolution < > swift-evolution@swift.org>:

>> So, I definitely think there is room for improvement here… how about
recycling the inheritance syntax?
>>
>> let controller: (UIViewController, UITableViewDatasource)
>
> This declares a tuple containing a UIViewController and a
UITableViewDataSource.
>
>> I added the braces because it would be really when you add the question
mark for an optional value; an alternative for this case would be
>>
>> let controller: Optional<UIViewController, UITableViewDatasource>
>
> This attempts to declare an optional with two generic types, which
doesn't work because Optional only has one type parameter. (But other
types, like Dictionary, *do* take two type parameters.)
>
> Swift does already have a syntax for declaring that a type must conform
to two (or more!) protocols:
>
> let controller: protocol<UITableViewDataSource, UITableViewDelegate>
>
> I think this could probably be extended to support one class type as
well, perhaps with a new name:
>
> let controller: all<UIViewController, UITableViewDataSource>
>
> --
> 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


(Haravikk) #16

The main conflict for using & and | would be with BitwiseOperationsType, but personally I’m not sure that would be such a big deal, given that many developers may never need to fiddle with values in a bitwise fashion, and use of & or | on type names (rather than variables) seems a clear enough distinction to me.

That said, I prefer the use of all and any instead, as it’s more explicit in its meaning.

···

On 11 Feb 2016, at 08:39, Thorsten Seitz via swift-evolution <swift-evolution@swift.org> wrote:

Jordan, I'm not sure if I understood you correctly, do you mean to use

   all<A, B> for intersection types (Ceylon's A & B), i.e. a type conforming to all listed types
   any<A, B> for union types (Ceylon's A | B), i.e. a type conforming to any of the listed types

That would be fine, too, I think, while a bit heavier than Ceylon's syntax (though I seem to remember from another thread that there was a problem with using Ceylon's syntax in Swift, though the reason escapes me at the moment).

-Thorsten


(Thorsten Seitz) #17

Ceylon uses & for intersection types (and | for union types) which I find quite intuitive, meaning a type which conforms to this AND that protocol/type (OR in the case of unions).

It works like expected, i.e.
A & B & A == A & B

or
typealias A = B & C
A & C == B & C
A & D == B & C & D

class A<T> {
        var x: T & B
}

var a: A<C>
a.x has type C & B

var b: A<B>
b.x has type B

etc.

-Thorsten

···

Am 10.02.2016 um 14:59 schrieb Ross O'Brien via swift-evolution <swift-evolution@swift.org>:

I agree with everything Brent just said.
My question would then be: how does this extend?

Continuing the example:
'typealias ViewControllerTableViewDataSource = all<UIViewController, UITableViewDataSource>'

It should then be possible to have a subtype of this which also conforms to UITableViewDelegate.
So, given the above, this would work:
'typealias ViewControllerTableViewPackage = all<UIViewController, UITableViewDataSource, UITableViewDelegate>'.
Would this also work?
'typealias ViewControllerTableViewPackage = all<ViewControllerTableViewDataSource, UITableViewDelegate>'
Assuming someone defined this typealias: 'typealias TableViewPackage = protocol<UITableViewDataSource, UITableViewDelegate>', would the above also be equivalent to this?:
'typealias ViewControllerTableViewPackage = all<UIViewController, TableViewPackage>'

The TableViewPackage protocol, defined above, is considered by Swift to be a 'non-nominal type'. Thus this is illegal:
'extension TableViewPackage'
(I don't know why. Perhaps a type conforming to the separate protocols has to opt-in to the combination?)

However, we can have the following:
'extension UITableViewDelegate where Self : UITableViewDataSource'
'extension UITableViewDelegate where Self : UIViewController'
'extension UITableViewDelegate where Self : UIViewController, Self : UITableViewDataSource'

Similarly we can't currently have this:
'extension UIViewController where Self : UITableViewDataSource, UITableViewDelegate'
because UIViewController is not a generic type (and this is part of the original complaint).

It would be nice to be able to write this out as: 'extension all<UIViewController, UITableViewDataSource, UITableViewDelegate>', even if it's just syntactic sugar for 'extension UITableViewDelegate where Self : UIViewController, Self : UITableViewDataSource'.

-- Ross

On Wed, Feb 10, 2016 at 1:44 PM, Maximilian Hünenberger <swift-evolution@swift.org> wrote:
In the thread "Partially constrained protocols" we have discussed a similar approach using where clauses:

        protocol<MyProtocol where Self: UIViewController>

- Maximilian

Am 10.02.2016 um 14:00 schrieb Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org>:

>> So, I definitely think there is room for improvement here… how about recycling the inheritance syntax?
>>
>> let controller: (UIViewController, UITableViewDatasource)
>
> This declares a tuple containing a UIViewController and a UITableViewDataSource.
>
>> I added the braces because it would be really when you add the question mark for an optional value; an alternative for this case would be
>>
>> let controller: Optional<UIViewController, UITableViewDatasource>
>
> This attempts to declare an optional with two generic types, which doesn't work because Optional only has one type parameter. (But other types, like Dictionary, *do* take two type parameters.)
>
> Swift does already have a syntax for declaring that a type must conform to two (or more!) protocols:
>
> let controller: protocol<UITableViewDataSource, UITableViewDelegate>
>
> I think this could probably be extended to support one class type as well, perhaps with a new name:
>
> let controller: all<UIViewController, UITableViewDataSource>
>
> --
> 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

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


(Jordan Rose) #18

No, both Brent and I were proposing replacing the "protocol" in "protocol<UITableViewDelegate, UITableViewDataSource>" with a different word. Brent's word was "all", as in "conforms to all of these"; mine (and JoeG's?) was "any", as in "any type conforming to these". So both of them correspond to Ceylon's "&".

(The other motivation for "any" or "Any" was by analogy with 'AnyObject' and the existing 'Any'; the latter simply becomes a short form for 'Any<>'.)

With the word "protocol" no longer in the type, we could then extend it to include a single class bound as well as protocol bounds.

Jordan

···

On Feb 11, 2016, at 0:39 , Thorsten Seitz <tseitz42@icloud.com> wrote:

Jordan, I'm not sure if I understood you correctly, do you mean to use

   all<A, B> for intersection types (Ceylon's A & B), i.e. a type conforming to all listed types
   any<A, B> for union types (Ceylon's A | B), i.e. a type conforming to any of the listed types

That would be fine, too, I think, while a bit heavier than Ceylon's syntax (though I seem to remember from another thread that there was a problem with using Ceylon's syntax in Swift, though the reason escapes me at the moment).

-Thorsten

Am 10.02.2016 um 18:26 schrieb Jordan Rose via swift-evolution <swift-evolution@swift.org>:

On Feb 10, 2016, at 5:00 , Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

So, I definitely think there is room for improvement here… how about recycling the inheritance syntax?

let controller: (UIViewController, UITableViewDatasource)

This declares a tuple containing a UIViewController and a UITableViewDataSource.

I added the braces because it would be really when you add the question mark for an optional value; an alternative for this case would be

let controller: Optional<UIViewController, UITableViewDatasource>

This attempts to declare an optional with two generic types, which doesn't work because Optional only has one type parameter. (But other types, like Dictionary, *do* take two type parameters.)

Swift does already have a syntax for declaring that a type must conform to two (or more!) protocols:

  let controller: protocol<UITableViewDataSource, UITableViewDelegate>

I think this could probably be extended to support one class type as well, perhaps with a new name:

  let controller: all<UIViewController, UITableViewDataSource>

We've been calling it "any" or "Any" (as in "any instance that is-a UIViewController and is-a UITableViewDataSource"), but I think this is the direction we've been talking about over here.

(Not that syntax bikeshedding can't still be useful.)

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


(Thorsten Seitz) #19

Thanks for clarifying! In that case I’d prefer Ceylon’s syntax as it seems to express the ideas with less room for confusion (but this probably belongs into another thread).

-Thorsten

···

Am 11.02.2016 um 18:38 schrieb Jordan Rose <jordan_rose@apple.com>:

No, both Brent and I were proposing replacing the "protocol" in "protocol<UITableViewDelegate, UITableViewDataSource>" with a different word. Brent's word was "all", as in "conforms to all of these"; mine (and JoeG's?) was "any", as in "any type conforming to these". So both of them correspond to Ceylon's "&".

(The other motivation for "any" or "Any" was by analogy with 'AnyObject' and the existing 'Any'; the latter simply becomes a short form for 'Any<>'.)

With the word "protocol" no longer in the type, we could then extend it to include a single class bound as well as protocol bounds.

Jordan

On Feb 11, 2016, at 0:39 , Thorsten Seitz <tseitz42@icloud.com <mailto:tseitz42@icloud.com>> wrote:

Jordan, I'm not sure if I understood you correctly, do you mean to use

   all<A, B> for intersection types (Ceylon's A & B), i.e. a type conforming to all listed types
   any<A, B> for union types (Ceylon's A | B), i.e. a type conforming to any of the listed types

That would be fine, too, I think, while a bit heavier than Ceylon's syntax (though I seem to remember from another thread that there was a problem with using Ceylon's syntax in Swift, though the reason escapes me at the moment).

-Thorsten

Am 10.02.2016 um 18:26 schrieb Jordan Rose via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:

On Feb 10, 2016, at 5:00 , Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

So, I definitely think there is room for improvement here… how about recycling the inheritance syntax?

let controller: (UIViewController, UITableViewDatasource)

This declares a tuple containing a UIViewController and a UITableViewDataSource.

I added the braces because it would be really when you add the question mark for an optional value; an alternative for this case would be

let controller: Optional<UIViewController, UITableViewDatasource>

This attempts to declare an optional with two generic types, which doesn't work because Optional only has one type parameter. (But other types, like Dictionary, *do* take two type parameters.)

Swift does already have a syntax for declaring that a type must conform to two (or more!) protocols:

  let controller: protocol<UITableViewDataSource, UITableViewDelegate>

I think this could probably be extended to support one class type as well, perhaps with a new name:

  let controller: all<UIViewController, UITableViewDataSource>

We've been calling it "any" or "Any" (as in "any instance that is-a UIViewController and is-a UITableViewDataSource"), but I think this is the direction we've been talking about over here.

(Not that syntax bikeshedding can't still be useful.)

Jordan
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


#20

I don't see union and intersection types either in the "goals list" or in the "non-goals list". Either way it should be a separate proposal.

- Maximilian

···

Am 11.02.2016 um 09:29 schrieb Thorsten Seitz <tseitz42@icloud.com>:

Ceylon uses & for intersection types (and | for union types) which I find quite intuitive, meaning a type which conforms to this AND that protocol/type (OR in the case of unions).

It works like expected, i.e.
A & B & A == A & B

or
typealias A = B & C
A & C == B & C
A & D == B & C & D

class A<T> {
        var x: T & B
}

var a: A<C>
a.x has type C & B

var b: A<B>
b.x has type B

etc.

-Thorsten

Am 10.02.2016 um 14:59 schrieb Ross O'Brien via swift-evolution <swift-evolution@swift.org>:

I agree with everything Brent just said.
My question would then be: how does this extend?

Continuing the example:
'typealias ViewControllerTableViewDataSource = all<UIViewController, UITableViewDataSource>'

It should then be possible to have a subtype of this which also conforms to UITableViewDelegate.
So, given the above, this would work:
'typealias ViewControllerTableViewPackage = all<UIViewController, UITableViewDataSource, UITableViewDelegate>'.
Would this also work?
'typealias ViewControllerTableViewPackage = all<ViewControllerTableViewDataSource, UITableViewDelegate>'
Assuming someone defined this typealias: 'typealias TableViewPackage = protocol<UITableViewDataSource, UITableViewDelegate>', would the above also be equivalent to this?:
'typealias ViewControllerTableViewPackage = all<UIViewController, TableViewPackage>'

The TableViewPackage protocol, defined above, is considered by Swift to be a 'non-nominal type'. Thus this is illegal:
'extension TableViewPackage'
(I don't know why. Perhaps a type conforming to the separate protocols has to opt-in to the combination?)

However, we can have the following:
'extension UITableViewDelegate where Self : UITableViewDataSource'
'extension UITableViewDelegate where Self : UIViewController'
'extension UITableViewDelegate where Self : UIViewController, Self : UITableViewDataSource'

Similarly we can't currently have this:
'extension UIViewController where Self : UITableViewDataSource, UITableViewDelegate'
because UIViewController is not a generic type (and this is part of the original complaint).

It would be nice to be able to write this out as: 'extension all<UIViewController, UITableViewDataSource, UITableViewDelegate>', even if it's just syntactic sugar for 'extension UITableViewDelegate where Self : UIViewController, Self : UITableViewDataSource'.

-- Ross

On Wed, Feb 10, 2016 at 1:44 PM, Maximilian Hünenberger <swift-evolution@swift.org> wrote:
In the thread "Partially constrained protocols" we have discussed a similar approach using where clauses:

        protocol<MyProtocol where Self: UIViewController>

- Maximilian

Am 10.02.2016 um 14:00 schrieb Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org>:

>> So, I definitely think there is room for improvement here… how about recycling the inheritance syntax?
>>
>> let controller: (UIViewController, UITableViewDatasource)
>
> This declares a tuple containing a UIViewController and a UITableViewDataSource.
>
>> I added the braces because it would be really when you add the question mark for an optional value; an alternative for this case would be
>>
>> let controller: Optional<UIViewController, UITableViewDatasource>
>
> This attempts to declare an optional with two generic types, which doesn't work because Optional only has one type parameter. (But other types, like Dictionary, *do* take two type parameters.)
>
> Swift does already have a syntax for declaring that a type must conform to two (or more!) protocols:
>
> let controller: protocol<UITableViewDataSource, UITableViewDelegate>
>
> I think this could probably be extended to support one class type as well, perhaps with a new name:
>
> let controller: all<UIViewController, UITableViewDataSource>
>
> --
> 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

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