[Pre-pitch] Allowing enums inside protocols?


(William Shipley) #1

Does anyone know if there's some good tech reason to not allow, like:

protocol Foozle {
  enum Errors: Error {
    case malformedFoozle
    case tooManyFoozles
  }
}

Like, to me all this is doing is giving “Errors” a nice namespace, but the compiler might have other thoughts.

-W


(Jon Hull) #2

I *really* want this as well.

I think there was a serious proposal to do this early in Swift 4. Not sure why it stalled, but I seem to remember it being technically possible.

Thanks,
Jon

···

On Jul 8, 2017, at 4:21 PM, William Shipley via swift-evolution <swift-evolution@swift.org> wrote:

Does anyone know if there's some good tech reason to not allow, like:

protocol Foozle {
  enum Errors: Error {
    case malformedFoozle
    case tooManyFoozles
  }
}

Like, to me all this is doing is giving “Errors” a nice namespace, but the compiler might have other thoughts.

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


(Akshay Hegde) #3

Wouldn’t the following work just as well for providing a namespace?

struct Foozle {
    enum Errors: Error {
        case malformedFoozle
        case tooManyFoozles
    }
}

~Akshay

···

On Jul 8, 2017, at 17:24, Jonathan Hull via swift-evolution <swift-evolution@swift.org> wrote:

I *really* want this as well.

I think there was a serious proposal to do this early in Swift 4. Not sure why it stalled, but I seem to remember it being technically possible.

Thanks,
Jon

On Jul 8, 2017, at 4:21 PM, William Shipley via swift-evolution <swift-evolution@swift.org> wrote:

Does anyone know if there's some good tech reason to not allow, like:

protocol Foozle {
  enum Errors: Error {
    case malformedFoozle
    case tooManyFoozles
  }
}

Like, to me all this is doing is giving “Errors” a nice namespace, but the compiler might have other thoughts.

-W
_______________________________________________
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


(Jon Hull) #4

The idea (at least for me) is to namespace the enum within the protocol, so that users of the protocol have everything neatly packaged. Right now I have to make a Separate “FoozleErrors” enum, which just feels messy.

I would really like to see us be able to nest Structs, Enums, and even other Protocols within a protocol, and it would just act as a namespace. Wil is right though, that if we can only have one, Enums give us the most bang for our buck. That is the case I run into most often. In addition to Error Enums, I also have a lot of places where protocol functions return a classification (as an enum), and it is cluttering the top-level namespace with things named “Foozle____".

It isn’t a huge issue (it doesn’t stop me from doing anything), but it is an annoyance that I run into all the time… I view the fact that Swift doesn’t support this as a bug.

Thanks,
Jon

···

On Jul 8, 2017, at 6:10 PM, Akshay Hegde <akshay_hegde@me.com> wrote:

Wouldn’t the following work just as well for providing a namespace?

struct Foozle {
    enum Errors: Error {
        case malformedFoozle
        case tooManyFoozles
    }
}

~Akshay

On Jul 8, 2017, at 17:24, Jonathan Hull via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I *really* want this as well.

I think there was a serious proposal to do this early in Swift 4. Not sure why it stalled, but I seem to remember it being technically possible.

Thanks,
Jon

On Jul 8, 2017, at 4:21 PM, William Shipley via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Does anyone know if there's some good tech reason to not allow, like:

protocol Foozle {
  enum Errors: Error {
    case malformedFoozle
    case tooManyFoozles
  }
}

Like, to me all this is doing is giving “Errors” a nice namespace, but the compiler might have other thoughts.

-W
_______________________________________________
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


(Xiaodi Wu) #5

At least one fairly complete draft for allowing concrete types to be
declared inside protocols was at some point a PR in the swift-evolution
repo. Worth taking a look at.

The chief source of complexity is in terms of how to refer to or capture
types or members of the containing type or protocol. In the draft I
remember, protocols could be nested inside types, and types could be nested
inside protocols. Whether and how a protocol with associated type
requirements inside a generic type inside another protocol with associated
type requirements can refer to types or members of the outermost protocol
gets quickly very convoluted; this requires careful design.

···

On Sat, Jul 8, 2017 at 20:59 Jonathan Hull via swift-evolution < swift-evolution@swift.org> wrote:

The idea (at least for me) is to namespace the enum within the protocol,
so that users of the protocol have everything neatly packaged. Right now I
have to make a Separate “FoozleErrors” enum, which just feels messy.

I would really like to see us be able to nest Structs, Enums, and even
other Protocols within a protocol, and it would just act as a namespace.
Wil is right though, that if we can only have one, Enums give us the most
bang for our buck. That is the case I run into most often. In addition to
Error Enums, I also have a lot of places where protocol functions return a
classification (as an enum), and it is cluttering the top-level namespace
with things named “Foozle____".

It isn’t a huge issue (it doesn’t stop me from doing anything), but it is
an annoyance that I run into all the time… I view the fact that Swift
doesn’t support this as a bug.

Thanks,
Jon

On Jul 8, 2017, at 6:10 PM, Akshay Hegde <akshay_hegde@me.com> wrote:

Wouldn’t the following work just as well for providing a namespace?

struct Foozle {

    enum Errors: Error {
        case malformedFoozle
        case tooManyFoozles
    }
}

~Akshay

On Jul 8, 2017, at 17:24, Jonathan Hull via swift-evolution < > swift-evolution@swift.org> wrote:

I *really* want this as well.

I think there was a serious proposal to do this early in Swift 4. Not
sure why it stalled, but I seem to remember it being technically possible.

Thanks,
Jon

On Jul 8, 2017, at 4:21 PM, William Shipley via swift-evolution < > swift-evolution@swift.org> wrote:

Does anyone know if there's some good tech reason to not allow, like:

protocol Foozle {
enum Errors: Error {
case malformedFoozle
case tooManyFoozles
}
}

Like, to me all this is doing is giving “Errors” a nice namespace, but the
compiler might have other thoughts.

-W
_______________________________________________
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


(Jon Hull) #6

Do you know why it was never brought to a vote?

I seem to remember us having a pretty good consensus. I think we decided to punt on nested generics by just not allowing nesting in them yet (which would be compatible since that is what happens now too). Then we would have a second proposal to deal with generics/associated more carefully.

···

On Jul 8, 2017, at 7:15 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

At least one fairly complete draft for allowing concrete types to be declared inside protocols was at some point a PR in the swift-evolution repo. Worth taking a look at.

The chief source of complexity is in terms of how to refer to or capture types or members of the containing type or protocol. In the draft I remember, protocols could be nested inside types, and types could be nested inside protocols. Whether and how a protocol with associated type requirements inside a generic type inside another protocol with associated type requirements can refer to types or members of the outermost protocol gets quickly very convoluted; this requires careful design.

On Sat, Jul 8, 2017 at 20:59 Jonathan Hull via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
The idea (at least for me) is to namespace the enum within the protocol, so that users of the protocol have everything neatly packaged. Right now I have to make a Separate “FoozleErrors” enum, which just feels messy.

I would really like to see us be able to nest Structs, Enums, and even other Protocols within a protocol, and it would just act as a namespace. Wil is right though, that if we can only have one, Enums give us the most bang for our buck. That is the case I run into most often. In addition to Error Enums, I also have a lot of places where protocol functions return a classification (as an enum), and it is cluttering the top-level namespace with things named “Foozle____".

It isn’t a huge issue (it doesn’t stop me from doing anything), but it is an annoyance that I run into all the time… I view the fact that Swift doesn’t support this as a bug.

Thanks,
Jon

On Jul 8, 2017, at 6:10 PM, Akshay Hegde <akshay_hegde@me.com <mailto:akshay_hegde@me.com>> wrote:

Wouldn’t the following work just as well for providing a namespace?

struct Foozle {

    enum Errors: Error {
        case malformedFoozle
        case tooManyFoozles
    }
}

~Akshay

On Jul 8, 2017, at 17:24, Jonathan Hull via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I *really* want this as well.

I think there was a serious proposal to do this early in Swift 4. Not sure why it stalled, but I seem to remember it being technically possible.

Thanks,
Jon

On Jul 8, 2017, at 4:21 PM, William Shipley via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Does anyone know if there's some good tech reason to not allow, like:

protocol Foozle {
  enum Errors: Error {
    case malformedFoozle
    case tooManyFoozles
  }
}

Like, to me all this is doing is giving “Errors” a nice namespace, but the compiler might have other thoughts.

-W
_______________________________________________
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

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


(Xiaodi Wu) #7

Do you know why it was never brought to a vote?

If I had to guess, it would be because the core team decided it's not in
scope.

As an aside not central to your question and not directed to you
specifically: There aren't votes in the evolution process; there are
community and core team reviews. The purpose, afaik, isn't to count the
number of replies that say "+1" or "-1."

I seem to remember us having a pretty good consensus. I think we decided
to punt on nested generics by just not allowing nesting in them yet (which
would be compatible since that is what happens now too). Then we would
have a second proposal to deal with generics/associated more carefully.

I'm not aware of any proposal text that punts on nested generics.

···

On Sat, Jul 8, 2017 at 10:52 PM, Jonathan Hull <jhull@gbis.com> wrote:

On Jul 8, 2017, at 7:15 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

At least one fairly complete draft for allowing concrete types to be
declared inside protocols was at some point a PR in the swift-evolution
repo. Worth taking a look at.

The chief source of complexity is in terms of how to refer to or capture
types or members of the containing type or protocol. In the draft I
remember, protocols could be nested inside types, and types could be nested
inside protocols. Whether and how a protocol with associated type
requirements inside a generic type inside another protocol with associated
type requirements can refer to types or members of the outermost protocol
gets quickly very convoluted; this requires careful design.

On Sat, Jul 8, 2017 at 20:59 Jonathan Hull via swift-evolution < > swift-evolution@swift.org> wrote:

The idea (at least for me) is to namespace the enum within the protocol,
so that users of the protocol have everything neatly packaged. Right now I
have to make a Separate “FoozleErrors” enum, which just feels messy.

I would really like to see us be able to nest Structs, Enums, and even
other Protocols within a protocol, and it would just act as a namespace.
Wil is right though, that if we can only have one, Enums give us the most
bang for our buck. That is the case I run into most often. In addition to
Error Enums, I also have a lot of places where protocol functions return a
classification (as an enum), and it is cluttering the top-level namespace
with things named “Foozle____".

It isn’t a huge issue (it doesn’t stop me from doing anything), but it is
an annoyance that I run into all the time… I view the fact that Swift
doesn’t support this as a bug.

Thanks,
Jon

On Jul 8, 2017, at 6:10 PM, Akshay Hegde <akshay_hegde@me.com> wrote:

Wouldn’t the following work just as well for providing a namespace?

struct Foozle {

    enum Errors: Error {
        case malformedFoozle
        case tooManyFoozles
    }
}

~Akshay

On Jul 8, 2017, at 17:24, Jonathan Hull via swift-evolution < >> swift-evolution@swift.org> wrote:

I *really* want this as well.

I think there was a serious proposal to do this early in Swift 4. Not
sure why it stalled, but I seem to remember it being technically possible.

Thanks,
Jon

On Jul 8, 2017, at 4:21 PM, William Shipley via swift-evolution < >> swift-evolution@swift.org> wrote:

Does anyone know if there's some good tech reason to not allow, like:

protocol Foozle {
enum Errors: Error {
case malformedFoozle
case tooManyFoozles
}
}

Like, to me all this is doing is giving “Errors” a nice namespace, but
the compiler might have other thoughts.

-W
_______________________________________________
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


(Karl) #8

Do you know why it was never brought to a vote?

If I had to guess, it would be because the core team decided it's not in scope.

That’s pretty-much what happened. I wanted to allow nesting arbitrary types in protocols (e.g. FloatingPoint.Sign) and vice-versa (e.g. UITableView.Delegate). Wasn’t in scope.

As an aside not central to your question and not directed to you specifically: There aren't votes in the evolution process; there are community and core team reviews. The purpose, afaik, isn't to count the number of replies that say "+1" or "-1."

I seem to remember us having a pretty good consensus. I think we decided to punt on nested generics by just not allowing nesting in them yet (which would be compatible since that is what happens now too). Then we would have a second proposal to deal with generics/associated more carefully.

I'm not aware of any proposal text that punts on nested generics.

Capturing generic type parameters between nested types works already. We lack the expressive ability to capture associated types between nested protocols (we would need generalised existentials). Capturing between generic types and associated types was controversial (and… yeah, that not exactly frictionless boundary between generic protocols and structural types is usually most people’s biggest problem with Swift’s generics).

Consider MyObject<T>.Delegate:

- Should we create a new protocol for every type T (allowing one object to conform to both MyObject<Int>.Delegate and MyObject<String>.Delegate)?, or
- Should there be one MyObject.Delegate protocol with an implicit associated-type “T”? e.g. "MyObject.Delegate where T == Int”. That would require "generalised existentials”.

So yeah, the proposal didn’t include capturing between nested protocols and types.

Also, I had some trouble nailing down the rules for when a nested type should be imported in to a conformer’s namespace. For example, you probably want Double.Sign to be an alias for FloatingPoint.Sign, but in general that might not always be true - especially if nested types and protocols can be added in extensions, things could get cluttered rather quickly. We don’t really have any formally-specified rules for unqualified lookup to take guidance from, either. In any case I think we should use the new protocol typealias lookup rules that appear to have popped up in Swift 3.2 - i.e. that typealiases inside the protocol body get inherited, but typealiases inside extensions don’t.

Long-term I really think we need to write down our rules for unqualified lookup. Something equivalent to this: http://en.cppreference.com/w/cpp/language/unqualified_lookup

- Karl

···

On 9. Jul 2017, at 06:06, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:
On Sat, Jul 8, 2017 at 10:52 PM, Jonathan Hull <jhull@gbis.com <mailto:jhull@gbis.com>> wrote: