Type information containing multiple additional protocols


(Daniel Muhra) #1

Currently it doesn’t seem possible to define a property or variable of a specific class that also implements one or more protocols.
Take as an example the following definition from Objective C:

NSManagedObject<NSCoding, Task>* someObject;

To my knowledge, currently it is only possible to define multiple protocols only:

var object : protocol<NSCoding, Task>

However, given the first example, sometimes it is not possible to restrict to protocols only. This becomes especially cumbersome, if you would need to cast down to such a construct within a single method and perform several steps which would require all those type information:

func doSomething(object: AnyObject) {
    if let managedObject = object as? NSManagedObject {
        // Do core data related stuff
    }
    
    if let task = object as? Task {
        // Do task related stuff
    }
}

In this case you now have managedObject and task though you operate on the same object. Also it is not (easily) possible to interleave actions of those two.

My first idea here would be to introduce an Objective C like style of type naming. This also has the benefit, that it is perfectly clear, whether a type name refers to a class or a protocol (without first having to check it).
The downside, of course, is that protocol type variables would become something like Any<MyProtocol>

Any other ideas are welcome, but the initial problem still stands and should be addressed.


(Jacob Bandes-Storch) #2

I think this is a very useful feature of Obj-C that I've missed several
times while writing Swift code.

However, calling it "TheClass<Protocol1, Protocol2>" directly conflicts
with the syntax for specifying generic type parameters.

If we use "protocol<TheClass, Protocol1, Protocol2>" for this case, then
`protocol` stops making sense. Maybe the keyword `class` could be allowed
instead, like "class<TheClass, Protocol1, Protocol2>".

Or, it might work to omit the keyword entirely, leaving only the angle
brackets:

class C {
    weak var delegate: <UIViewController, UICollectionViewDelegate>?
}

if let task = object as? <NSManagedObject, Task> {
    task.coreDataRelatedFunction()
    task.taskRelatedFunction()
}

Jacob Bandes-Storch

···

On Fri, Dec 4, 2015 at 3:07 PM, Daniel Muhra <daniel.muhra@gmail.com> wrote:

Currently it doesn’t seem possible to define a property or variable of a
specific class that also implements one or more protocols.
Take as an example the following definition from Objective C:

NSManagedObject<NSCoding, Task>* someObject;

To my knowledge, currently it is only possible to define multiple
protocols only:

var object : protocol<NSCoding, Task>

However, given the first example, sometimes it is not possible to restrict
to protocols only. This becomes especially cumbersome, if you would need to
cast down to such a construct within a single method and perform several
steps which would require all those type information:

func doSomething(object: AnyObject) {
    if let managedObject = object as? NSManagedObject {
        // Do core data related stuff
    }

    if let task = object as? Task {
        // Do task related stuff
    }
}

In this case you now have managedObject and task though you operate on the
same object. Also it is not (easily) possible to interleave actions of
those two.

My first idea here would be to introduce an Objective C like style of type
naming. This also has the benefit, that it is perfectly clear, whether a
type name refers to a class or a protocol (without first having to check
it).
The downside, of course, is that protocol type variables would become
something like Any<MyProtocol>

Any other ideas are welcome, but the initial problem still stands and
should be addressed.

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


(Jordan Rose) #3

At one point we talked about co-opting "Any" for this purpose, i.e. replacing the "protocol<…>" syntax with "Any<…>". Like a concrete type, you're not required to provide arguments, so "Any" by itself doesn't change meaning. Like an inheritance clause, the compiler would check if you ever had more than one class there.

Jordan

···

On Dec 4, 2015, at 23:38 , Jacob Bandes-Storch <jtbandes@gmail.com> wrote:

I think this is a very useful feature of Obj-C that I've missed several times while writing Swift code.

However, calling it "TheClass<Protocol1, Protocol2>" directly conflicts with the syntax for specifying generic type parameters.

If we use "protocol<TheClass, Protocol1, Protocol2>" for this case, then `protocol` stops making sense. Maybe the keyword `class` could be allowed instead, like "class<TheClass, Protocol1, Protocol2>".

Or, it might work to omit the keyword entirely, leaving only the angle brackets:

class C {
    weak var delegate: <UIViewController, UICollectionViewDelegate>?
}

if let task = object as? <NSManagedObject, Task> {
    task.coreDataRelatedFunction()
    task.taskRelatedFunction()
}

Jacob Bandes-Storch

On Fri, Dec 4, 2015 at 3:07 PM, Daniel Muhra <daniel.muhra@gmail.com <mailto:daniel.muhra@gmail.com>> wrote:
Currently it doesn’t seem possible to define a property or variable of a specific class that also implements one or more protocols.
Take as an example the following definition from Objective C:

NSManagedObject<NSCoding, Task>* someObject;

To my knowledge, currently it is only possible to define multiple protocols only:

var object : protocol<NSCoding, Task>

However, given the first example, sometimes it is not possible to restrict to protocols only. This becomes especially cumbersome, if you would need to cast down to such a construct within a single method and perform several steps which would require all those type information:

func doSomething(object: AnyObject) {
    if let managedObject = object as? NSManagedObject {
        // Do core data related stuff
    }
    
    if let task = object as? Task {
        // Do task related stuff
    }
}

In this case you now have managedObject and task though you operate on the same object. Also it is not (easily) possible to interleave actions of those two.

My first idea here would be to introduce an Objective C like style of type naming. This also has the benefit, that it is perfectly clear, whether a type name refers to a class or a protocol (without first having to check it).
The downside, of course, is that protocol type variables would become something like Any<MyProtocol>

Any other ideas are welcome, but the initial problem still stands and should be addressed.

_______________________________________________
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


(Lily Ballard) #4

Oh that's clever. I like that. It doesn't have a big impact on the
language and it makes reasonable sense when read. We could also
establish convention (possibly backed up by warnings) that says that if
Any<...> contains a class, the class name must come first.

-Kevin Ballard

···

On Tue, Dec 15, 2015, at 06:27 PM, Jordan Rose via swift-evolution wrote:

At one point we talked about co-opting "Any" for this purpose, i.e.
replacing the "protocol<…>" syntax with "Any<…>". Like a concrete
type, you're not required to provide arguments, so "Any" by itself
doesn't change meaning. Like an inheritance clause, the compiler would
check if you ever had more than one class there.

Jordan

On Dec 4, 2015, at 23:38 , Jacob Bandes-Storch >> <jtbandes@gmail.com> wrote:

I think this is a very useful feature of Obj-C that I've missed
several times while writing Swift code.

However, calling it "TheClass<Protocol1, Protocol2>" directly
conflicts with the syntax for specifying generic type parameters.

If we use "protocol<TheClass, Protocol1, Protocol2>" for this case,
then `protocol` stops making sense. Maybe the keyword `class` could
be allowed instead, like "class<TheClass, Protocol1, Protocol2>".

Or, it might work to omit the keyword entirely, leaving only the
angle brackets:

class C { weak var delegate: <UIViewController,
>? }

if let task = object as? <NSManagedObject, Task> {
task.coreDataRelatedFunction() task.taskRelatedFunction() }

Jacob Bandes-Storch

On Fri, Dec 4, 2015 at 3:07 PM, Daniel >> Muhra<daniel.muhra@gmail.com>wrote:

Currently it doesn’t seem possible to define a property or variable
of a specific class that also implements one or more protocols. Take
as an example the following definition from Objective C:

NSManagedObject<NSCoding, Task>* someObject;

To my knowledge, currently it is only possible to define multiple
protocols only:

var object : protocol<NSCoding, Task>

However, given the first example, sometimes it is not possible to
restrict to protocols only. This becomes especially cumbersome, if
you would need to cast down to such a construct within a single
method and perform several steps which would require all those type
information:

funcdoSomething(object:AnyObject) { ifletmanagedObject =
objectas?NSManagedObject{ // Do core data related stuff }

iflettask = objectas?Task{ // Do task related stuff } }

In this case you now have managedObject and task though you operate
on the same object. Also it is not (easily) possible to interleave
actions of those two.

My first idea here would be to introduce an Objective C like style
of type naming. This also has the benefit, that it is perfectly
clear, whether a type name refers to a class or a protocol (without
first having to check it). The downside, of course, is that protocol
type variables would become something like Any<MyProtocol>

Any other ideas are welcome, but the initial problem still stands
and should be addressed.

_______________________________________________
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


(Marc Knaup) #5

What about an approach like this:

// require value to be of type UIViewController AND conform to protocol
MySpecialProtocol
let specialViewController: (UIViewController & MySpecialProtocol) = …

// require value to be of type Bool OR Double OR String OR SomeProtocol
let value: (Bool | Double | String | SomeProtocol)
switch value {
   case let _ as Bool: …
   case let _ as Double: …
   case let _ as String: …
   case let _ as SomeProtocol: …
   // no default necessary
}

No need to mess with the <> syntax or requiring the use of any keyword.
Just reusing binary logic for types.

···

On Wed, Dec 16, 2015 at 3:40 AM, Kevin Ballard via swift-evolution < swift-evolution@swift.org> wrote:

Oh that's clever. I like that. It doesn't have a big impact on the
language and it makes reasonable sense when read. We could also establish
convention (possibly backed up by warnings) that says that if Any<...>
contains a class, the class name must come first.

-Kevin Ballard

On Tue, Dec 15, 2015, at 06:27 PM, Jordan Rose via swift-evolution wrote:

At one point we talked about co-opting "Any" for this purpose, i.e.
replacing the "protocol<…>" syntax with "Any<…>". Like a concrete type,
you're not required to provide arguments, so "Any" by itself doesn't change
meaning. Like an inheritance clause, the compiler would check if you ever
had more than one class there.

Jordan

On Dec 4, 2015, at 23:38 , Jacob Bandes-Storch <jtbandes@gmail.com> wrote:

I think this is a very useful feature of Obj-C that I've missed several
times while writing Swift code.

However, calling it "TheClass<Protocol1, Protocol2>" directly conflicts
with the syntax for specifying generic type parameters.

If we use "protocol<TheClass, Protocol1, Protocol2>" for this case, then
`protocol` stops making sense. Maybe the keyword `class` could be allowed
instead, like "class<TheClass, Protocol1, Protocol2>".

Or, it might work to omit the keyword entirely, leaving only the angle
brackets:

class C {
    weak var delegate: <UIViewController, UICollectionViewDelegate>?
}

if let task = object as? <NSManagedObject, Task> {
    task.coreDataRelatedFunction()
    task.taskRelatedFunction()
}

Jacob Bandes-Storch

On Fri, Dec 4, 2015 at 3:07 PM, Daniel Muhra<daniel.muhra@gmail.com>wrote:

Currently it doesn’t seem possible to define a property or variable of a
specific class that also implements one or more protocols.
Take as an example the following definition from Objective C:

NSManagedObject<NSCoding, Task>* someObject;

To my knowledge, currently it is only possible to define multiple
protocols only:

var object : protocol<NSCoding, Task>

However, given the first example, sometimes it is not possible to restrict
to protocols only. This becomes especially cumbersome, if you would need to
cast down to such a construct within a single method and perform several
steps which would require all those type information:

funcdoSomething(object:AnyObject) {
ifletmanagedObject = objectas?NSManagedObject{
// Do core data related stuff
}

iflettask = objectas?Task{
// Do task related stuff
}
}

In this case you now have managedObject and task though you operate on the
same object. Also it is not (easily) possible to interleave actions of
those two.

My first idea here would be to introduce an Objective C like style of type
naming. This also has the benefit, that it is perfectly clear, whether a
type name refers to a class or a protocol (without first having to check
it).
The downside, of course, is that protocol type variables would become
something like Any<MyProtocol>

Any other ideas are welcome, but the initial problem still stands and
should be addressed.

_______________________________________________
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

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


(Matthew Johnson) #6

// require value to be of type Bool OR Double OR String OR SomeProtocol
let value: (Bool | Double | String | SomeProtocol)
switch value {
   case let _ as Bool: …
   case let _ as Double: …
   case let _ as String: …
   case let _ as SomeProtocol: …
   // no default necessary
}

This is a structural union type which has received considerable discussion with commentary from core team members already in the with a subject something like "STL and Either". You may be interested in reading that discussion. The summary is that we are unlikely to see it without extremely compelling use cases.


(Marc Knaup) #7

Enumerations are a good example.
Or JSON nodes.

https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151214/002474.html

···

On Dec 16, 2015 16:05, "Matthew Johnson" <matthew@anandabits.com> wrote:

// require value to be of type Bool OR Double OR String OR SomeProtocol
let value: (Bool | Double | String | SomeProtocol)
switch value {
   case let _ as Bool: …
   case let _ as Double: …
   case let _ as String: …
   case let _ as SomeProtocol: …
   // no default necessary
}

This is a structural union type which has received considerable discussion
with commentary from core team members already in the with a subject
something like "STL and Either". You may be interested in reading that
discussion. The summary is that we are unlikely to see it without
extremely compelling use cases.


(Matthew Johnson) #8

I don’t believe the implementers who would need to face the complexities in the implementation believe those are compelling examples. It needs to be clear why a structural union is necessary rather than an enum. To be clear: structural unions are to enums as tuples are to structs.

···

On Dec 16, 2015, at 9:16 AM, Marc Knaup <marc@knaup.koeln> wrote:

Enumerations are a good example.
Or JSON nodes.

https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151214/002474.html
On Dec 16, 2015 16:05, "Matthew Johnson" <matthew@anandabits.com <mailto:matthew@anandabits.com>> wrote:

// require value to be of type Bool OR Double OR String OR SomeProtocol
let value: (Bool | Double | String | SomeProtocol)
switch value {
   case let _ as Bool: …
   case let _ as Double: …
   case let _ as String: …
   case let _ as SomeProtocol: …
   // no default necessary
}

This is a structural union type which has received considerable discussion with commentary from core team members already in the with a subject something like "STL and Either". You may be interested in reading that discussion. The summary is that we are unlikely to see it without extremely compelling use cases.