[Idea] Generic subscripts


(Brent Royal-Gordon) #1

I'm looking for consensus on, and a coalition for, including generic subscripts in Phase 1 of the Swift 4 design cycle.

The Need

···

-------------

While prototyping my deferred [SE-0132][], I ran into trouble introducing `RangeExpression`, an abstraction to make the introduction of subrange features easier. Since RangeExpression is a protocol compatible with any index type, it has to have an associated type, and thus cannot be handled with an existential. I therefore had to add an overloaded subscript for each type, which partially defeated the purpose of having the protocol.

The lack of generic subscripts also forced a nasty workaround for a convenience subscript in [SE-0131][]. That proposal extends `Dictionary where Key == AnyHashable` (actually a hidden `_AnyHashableProtocol`, but that's a different story) with a convenience subscript which takes any `Hashable` type—except that, because generic subscripts are impossible, [it instead has to take a hidden `_Hashable` type instead][anyhash-subscript].

The generics manifesto suggests a third use case: [a subscript that can take any Collection of Index][manifesto].

The lack of this feature at the very least impacts binary compatibility directly. It also affects source compatibility in that features like subranges are designed around its absence, forcing workarounds which affect userspace. I see good reasons to do it now and few to delay.

Prior Art
-----------

As mentioned, SE-0131 and SE-0132 would have benefited from this feature.

After a brief and mostly positive [discussion][], Harlan Haskins and Robert Widmann submitted a [pull request][] late in the Swift 3 cycle for generic and throwing subscripts. Personally, I think throwing subscripts are something we should include, but they're a separate issue and may not be appropriate for Phase 1; I would suggest severing the two parts of the proposal.

Next Steps
---------------

What I'd like to figure out at this point is:

* Who is interested in this feature?

* Should it be severed from throwing subscripts?

* Does the core team agree that this is in Phase 1's scope?

* Do the people who might be able to implement this have any comments on it?

  [SE-0132]: <https://github.com/apple/swift-evolution/blob/master/proposals/0132-sequence-end-ops.md>
  [SE-0131]: <https://github.com/apple/swift-evolution/blob/master/proposals/0131-anyhashable.md#detailed-design>
  [anyhash-subscript]: <https://github.com/apple/swift/blob/e051c61c4d7eb33cdbb47b8ac04eae38203a61e6/stdlib/public/core/HashedCollectionsAnyHashableExtensions.swift.gyb#L147>
  [manifesto]: <https://github.com/apple/swift/blob/e3d8448bbdd059a55a6e72c24d07e994afaf5926/docs/GenericsManifesto.md#generic-subscripts>
  [discussion]: <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160620/021450.html>
  [pull request]: <https://github.com/apple/swift-evolution/pull/372>

--
Brent Royal-Gordon
Architechies


(Matthew Johnson) #2

I'm looking for consensus on, and a coalition for, including generic subscripts in Phase 1 of the Swift 4 design cycle.

The Need
-------------

While prototyping my deferred [SE-0132][], I ran into trouble introducing `RangeExpression`, an abstraction to make the introduction of subrange features easier. Since RangeExpression is a protocol compatible with any index type, it has to have an associated type, and thus cannot be handled with an existential. I therefore had to add an overloaded subscript for each type, which partially defeated the purpose of having the protocol.

The lack of generic subscripts also forced a nasty workaround for a convenience subscript in [SE-0131][]. That proposal extends `Dictionary where Key == AnyHashable` (actually a hidden `_AnyHashableProtocol`, but that's a different story) with a convenience subscript which takes any `Hashable` type—except that, because generic subscripts are impossible, [it instead has to take a hidden `_Hashable` type instead][anyhash-subscript].

The generics manifesto suggests a third use case: [a subscript that can take any Collection of Index][manifesto].

The lack of this feature at the very least impacts binary compatibility directly. It also affects source compatibility in that features like subranges are designed around its absence, forcing workarounds which affect userspace. I see good reasons to do it now and few to delay.

Prior Art
-----------

As mentioned, SE-0131 and SE-0132 would have benefited from this feature.

After a brief and mostly positive [discussion][], Harlan Haskins and Robert Widmann submitted a [pull request][] late in the Swift 3 cycle for generic and throwing subscripts. Personally, I think throwing subscripts are something we should include, but they're a separate issue and may not be appropriate for Phase 1; I would suggest severing the two parts of the proposal.

Next Steps
---------------

What I'd like to figure out at this point is:

* Who is interested in this feature?

I am interested in this feature, both for specific applications as well as because it lifts what feels like an arbitrary restriction.

One very common use case is in libraries that handle loosely typed data (JSON, Plist, etc).

It’s also worth noting that they will allow us to simulate higher-rank functions more directly than we can today (with subscript as function application).

* Should it be severed from throwing subscripts?

Throwing subscripts are important, but don’t necessarily need to be introduced at the same time as generic subscripts. However, the use case of libraries that handle loosely typed data will require both. I believe that use case was the motivation for the proposal introduced by Harlan and Robert which is why both features were included.

···

On Aug 3, 2016, at 2:25 AM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

* Does the core team agree that this is in Phase 1's scope?

* Do the people who might be able to implement this have any comments on it?

  [SE-0132]: <https://github.com/apple/swift-evolution/blob/master/proposals/0132-sequence-end-ops.md>
  [SE-0131]: <https://github.com/apple/swift-evolution/blob/master/proposals/0131-anyhashable.md#detailed-design>
  [anyhash-subscript]: <https://github.com/apple/swift/blob/e051c61c4d7eb33cdbb47b8ac04eae38203a61e6/stdlib/public/core/HashedCollectionsAnyHashableExtensions.swift.gyb#L147>
  [manifesto]: <https://github.com/apple/swift/blob/e3d8448bbdd059a55a6e72c24d07e994afaf5926/docs/GenericsManifesto.md#generic-subscripts>
  [discussion]: <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160620/021450.html>
  [pull request]: <https://github.com/apple/swift-evolution/pull/372>

--
Brent Royal-Gordon
Architechies

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


(Chris Lattner) #3

I'm looking for consensus on, and a coalition for, including generic subscripts in Phase 1 of the Swift 4 design cycle.

What I'd like to figure out at this point is:

* Who is interested in this feature?

This is a very commonly requested feature. I consider it an obvious omission, not something that needs extensive design work. A proposal would be appropriate to capture the effort though. It should include generic properties as well (generic over the result type).

* Should it be severed from throwing subscripts?

Yes, perfectly reasonable.

* Does the core team agree that this is in Phase 1's scope?

I’ll defer to the standard library gurus to figure this out. It doesn’t sound like one of the most critical missing features, but I would love to see this happen at some point.

-Chris

···

On Aug 3, 2016, at 12:25 AM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:


(Tino) #4

Since RangeExpression is a protocol compatible with any index type, it has to have an associated type

I haven't read all linked information, but would the situation change with generic protocols?
Thinks like "AnyGenerator" afaics would be superfluous if we had "protocol Generator<Type>", and the same might be true for RangeExpression.


(Haravikk) #5

* Who is interested in this feature?

Me definitely, everyone probably.

* Should it be severed from throwing subscripts?

That depends I guess; subscripts are basically functions anyway so it didn't make a lot of sense to me that they lacked features that functions have, so if implementing both of these features is basically just a case of linking up the same behaviour from functions then I say do them simultaneously if possible. I don't know much about the actual implementation details though so obviously someone else should make a final decision :wink:

Basically I'm in favour making subscripts have as much in common with functions as possible; in fact they really should just be a property-like shorthand for a regular function behind the scenes.


(Brent Royal-Gordon) #6

No, this is not an appropriate use case for generic protocols. (Nor is Generator/IteratorProtocol, for that matter.)

Generic protocols would be for cases where a single concrete instance can conform to a protocol using several different types. Genuine use cases for that do exist, but they're few and far between.

···

On Aug 3, 2016, at 1:57 AM, Tino Heth <2th@gmx.de> wrote:

Since RangeExpression is a protocol compatible with any index type, it has to have an associated type

I haven't read all linked information, but would the situation change with generic protocols?
Thinks like "AnyGenerator" afaics would be superfluous if we had "protocol Generator<Type>", and the same might be true for RangeExpression.

--
Brent Royal-Gordon
Architechies


(Matthew Johnson) #7

Since RangeExpression is a protocol compatible with any index type, it has to have an associated type

I haven't read all linked information, but would the situation change with generic protocols?
Thinks like "AnyGenerator" afaics would be superfluous if we had "protocol Generator<Type>", and the same might be true for RangeExpression.

No, this is not an appropriate use case for generic protocols. (Nor is Generator/IteratorProtocol, for that matter.)

Generic protocols would be for cases where a single concrete instance can conform to a protocol using several different types. Genuine use cases for that do exist, but they're few and far between.

Yes, this feature is called “multi-parameter type classes” in Haskell. Those interested in proposing it in Swift might be interested in looking at how the feature is used in Haskell.

···

On Aug 3, 2016, at 4:16 AM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

On Aug 3, 2016, at 1:57 AM, Tino Heth <2th@gmx.de> wrote:

--
Brent Royal-Gordon
Architechies

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


(Jacob Bandes-Storch) #8

+1 from me on this feature as well. It seems like a pretty obvious way in
which subscripts should be like functions, but aren't yet.

Would there be any need for setters and getters to have different generic
parameters? I suppose today there's only one place to specify the type of
the parameters, and the type of the value being retrieved/set, so it's a
moot point.

···

On Wed, Aug 3, 2016 at 6:33 AM Matthew Johnson via swift-evolution < swift-evolution@swift.org> wrote:

> On Aug 3, 2016, at 2:25 AM, Brent Royal-Gordon via swift-evolution < > swift-evolution@swift.org> wrote:
>
> I'm looking for consensus on, and a coalition for, including generic
subscripts in Phase 1 of the Swift 4 design cycle.
>
> The Need
> -------------
>
> While prototyping my deferred [SE-0132][], I ran into trouble
introducing `RangeExpression`, an abstraction to make the introduction of
subrange features easier. Since RangeExpression is a protocol compatible
with any index type, it has to have an associated type, and thus cannot be
handled with an existential. I therefore had to add an overloaded subscript
for each type, which partially defeated the purpose of having the protocol.
>
> The lack of generic subscripts also forced a nasty workaround for a
convenience subscript in [SE-0131][]. That proposal extends `Dictionary
where Key == AnyHashable` (actually a hidden `_AnyHashableProtocol`, but
that's a different story) with a convenience subscript which takes any
`Hashable` type—except that, because generic subscripts are impossible, [it
instead has to take a hidden `_Hashable` type instead][anyhash-subscript].
>
> The generics manifesto suggests a third use case: [a subscript that can
take any Collection of Index][manifesto].
>
> The lack of this feature at the very least impacts binary compatibility
directly. It also affects source compatibility in that features like
subranges are designed around its absence, forcing workarounds which affect
userspace. I see good reasons to do it now and few to delay.
>
> Prior Art
> -----------
>
> As mentioned, SE-0131 and SE-0132 would have benefited from this feature.
>
> After a brief and mostly positive [discussion][], Harlan Haskins and
Robert Widmann submitted a [pull request][] late in the Swift 3 cycle for
generic and throwing subscripts. Personally, I think throwing subscripts
are something we should include, but they're a separate issue and may not
be appropriate for Phase 1; I would suggest severing the two parts of the
proposal.
>
> Next Steps
> ---------------
>
> What I'd like to figure out at this point is:
>
> * Who is interested in this feature?

I am interested in this feature, both for specific applications as well as
because it lifts what feels like an arbitrary restriction.

One very common use case is in libraries that handle loosely typed data
(JSON, Plist, etc).

It’s also worth noting that they will allow us to simulate higher-rank
functions more directly than we can today (with subscript as function
application).

>
> * Should it be severed from throwing subscripts?

Throwing subscripts are important, but don’t necessarily need to be
introduced at the same time as generic subscripts. However, the use case
of libraries that handle loosely typed data will require both. I believe
that use case was the motivation for the proposal introduced by Harlan and
Robert which is why both features were included.

>
> * Does the core team agree that this is in Phase 1's scope?
>
> * Do the people who might be able to implement this have any comments on
it?
>
>
>
> [SE-0132]: <
https://github.com/apple/swift-evolution/blob/master/proposals/0132-sequence-end-ops.md
>
> [SE-0131]: <
https://github.com/apple/swift-evolution/blob/master/proposals/0131-anyhashable.md#detailed-design
>
> [anyhash-subscript]: <
https://github.com/apple/swift/blob/e051c61c4d7eb33cdbb47b8ac04eae38203a61e6/stdlib/public/core/HashedCollectionsAnyHashableExtensions.swift.gyb#L147
>
> [manifesto]: <
https://github.com/apple/swift/blob/e3d8448bbdd059a55a6e72c24d07e994afaf5926/docs/GenericsManifesto.md#generic-subscripts
>
> [discussion]: <
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160620/021450.html
>
> [pull request]: <https://github.com/apple/swift-evolution/pull/372
>
>
> --
> 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