Generic Subscripts

Both. Usability-wise, it's no worse than f<T>() -> T, which has its
(rare) uses today and doesn't cause a problem when it's not used.
Ideally I'd like to be able to guide deduction to pick a sensible
default for T when there's insufficient type context, but that's a
separable feature.

···

on Sun Jan 15 2017, John McCall <rjmccall-AT-apple.com> wrote:

On Jan 14, 2017, at 6:41 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:
on Fri Jan 13 2017, John McCall <swift-evolution@swift.org> wrote:

I'm also not sure we'd ever want the element type to be inferred from
context like this. Generic subscripts as I see it are about being
generic over *indexes*, not somehow about presenting a polymorphic
value.

Actually I *would* want to be able to do that, though I admit it's the
1% case (or less).

Would you actually want the value type to be inferred, or you would
just want it to be allowed to vary according to the index type?
Because the former sounds like a huge usability issue.

--
-Dave

Y'all brought up plenty of examples I hadn't thought of, so 1% might be
too low.

···

on Sun Jan 15 2017, Jacob Bandes-Storch <jtbandes-AT-gmail.com> wrote:

On Sat, Jan 14, 2017 at 3:41 PM, Dave Abrahams via swift-evolution < > swift-evolution@swift.org> wrote:

on Fri Jan 13 2017, John McCall <swift-evolution@swift.org> wrote:

> I'm also not sure we'd ever want the element type to be inferred from
> context like this. Generic subscripts as I see it are about being
> generic over *indexes*, not somehow about presenting a polymorphic
> value.

Actually I *would* want to be able to do that, though I admit it's the
1% case (or less).

1%? Wouldn't many JSON libraries, for instance, be eager to take advantage
of this?

--
-Dave

I'm also not sure we'd ever want the element type to be inferred from
context like this. Generic subscripts as I see it are about being
generic over *indexes*, not somehow about presenting a polymorphic
value.

Actually I *would* want to be able to do that, though I admit it's the
1% case (or less).

Would you actually want the value type to be inferred, or you would
just want it to be allowed to vary according to the index type?
Because the former sounds like a huge usability issue.

Both. Usability-wise, it's no worse than f<T>() -> T, which has its
(rare) uses today and doesn't cause a problem when it's not used.

Well, I'm assuming you would like to be able to do things like call mutating methods on these things. Maybe not in the use case you're thinking of, though?

Ideally I'd like to be able to guide deduction to pick a sensible
default for T when there's insufficient type context, but that's a
separable feature.

Yes, defaulting would fix the usability problem.

John.

···

On Jan 15, 2017, at 7:22 PM, Dave Abrahams <dabrahams@apple.com> wrote:
on Sun Jan 15 2017, John McCall <rjmccall-AT-apple.com> wrote:

On Jan 14, 2017, at 6:41 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:
on Fri Jan 13 2017, John McCall <swift-evolution@swift.org> wrote:

This can be made typesafe if the ObjectIdentifier of the archetype is stored with the key and checked on retrieval.

~Robert Widmann

2017/01/23 11:43、Thorsten Seitz via swift-evolution <swift-evolution@swift.org> のメッセージ:

···

Am 14.01.2017 um 14:50 schrieb Gwendal Roué via swift-evolution <swift-evolution@swift.org>:

Where generic subscripts are concerned, there are a couple of different things to express:
- Generic parameter (I can understand various co-ordinates for the data)
- Generic return type (I can construct your preferred representation of the data)
- Generic setter type (I can set the data using various compatible types):

I think all of these should be expressed with a single generic signature on the subscript itself. The element type passed to the setter and returned from the getter should be the same IMO, otherwise it’s not clear how it will work.

Yes. It's quite important that any particular subscript reference is still a single consistent entity, even if generic; we would not want, say, a read-modify-write access to be able to somehow invoke the getter and setter at different generic arguments, or to traffic in different element types.

I'm also not sure we'd ever want the element type to be inferred from context like this. Generic subscripts as I see it are about being generic over *indexes*, not somehow about presenting a polymorphic value.

This is a consequence of your vision of subscript. If interesting, it is also limiting for no real purpose.

As the developer of a Swift database library, I'd like to offer a better API than the following:

    // Current state of affairs
    let name: String = row.value(named: "name")
    let bookCount: Int = row.value(named: "bookCount")
    let hasBooks: Bool = row.value(named: "bookCount")

Instead, I wish I could offer GRDB.swift would let its users write:

    // With improved subscripts
    let name: String = row["name"]
    let bookCount: Int = row["bookCount"]
    let hasBooks: Bool = row["bookCount"]

And this requires genericity on return type.

This is not typesafe at all if the type does not depend on the argument. I'd prefer keys carrying the meta information of their respective database column keeping the whole API typesafe.

-Thorsten

Gwendal

_______________________________________________
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

Where generic subscripts are concerned, there are a couple of different things to express:
- Generic parameter (I can understand various co-ordinates for the data)
- Generic return type (I can construct your preferred representation of the data)
- Generic setter type (I can set the data using various compatible types):

I think all of these should be expressed with a single generic signature on the subscript itself. The element type passed to the setter and returned from the getter should be the same IMO, otherwise it’s not clear how it will work.

Yes. It's quite important that any particular subscript reference is still a single consistent entity, even if generic; we would not want, say, a read-modify-write access to be able to somehow invoke the getter and setter at different generic arguments, or to traffic in different element types.

I'm also not sure we'd ever want the element type to be inferred from context like this. Generic subscripts as I see it are about being generic over *indexes*, not somehow about presenting a polymorphic value.

This is a consequence of your vision of subscript. If interesting, it is also limiting for no real purpose.

As the developer of a Swift database library, I'd like to offer a better API than the following:

    // Current state of affairs
    let name: String = row.value(named: "name")
    let bookCount: Int = row.value(named: "bookCount")
    let hasBooks: Bool = row.value(named: "bookCount")

Instead, I wish I could offer GRDB.swift would let its users write:

    // With improved subscripts
    let name: String = row["name"]
    let bookCount: Int = row["bookCount"]
    let hasBooks: Bool = row["bookCount"]

And this requires genericity on return type.

This is not typesafe at all if the type does not depend on the argument. I'd prefer keys carrying the meta information of their respective database column keeping the whole API typesafe.

As long as your personal preference has no impact on return-type genericity subscripts adoption, I'm fine with it :-)

Gwendal

I'm also not sure we'd ever want the element type to be inferred from
context like this. Generic subscripts as I see it are about being
generic over *indexes*, not somehow about presenting a polymorphic
value.

Actually I *would* want to be able to do that, though I admit it's the
1% case (or less).

Would you actually want the value type to be inferred, or you would
just want it to be allowed to vary according to the index type?
Because the former sounds like a huge usability issue.

Both. Usability-wise, it's no worse than f<T>() -> T, which has its
(rare) uses today and doesn't cause a problem when it's not used.

Well, I'm assuming you would like to be able to do things like call
mutating methods on these things.

Yes. That's already *possible* even without a default:

    func mutate<T, R>(_ x: inout T, applying body: (inout T)->R) -> R {
      return body(&x)
    }

    mutate(&thingWithGenericSubscript[3]) {
      (a: inout X)->() in a.mutatingMethod() // deduce X
    }

Obviously this is awful. The default mentioned below helps eliminate
the awfulness.

But not all subscripts are, or need to be, get/set, and even without the
default, the feature would be useful with get-only subscripts.

···

on Sun Jan 15 2017, John McCall <rjmccall-AT-apple.com> wrote:

On Jan 15, 2017, at 7:22 PM, Dave Abrahams <dabrahams@apple.com> wrote:
on Sun Jan 15 2017, John McCall <rjmccall-AT-apple.com> wrote:

On Jan 14, 2017, at 6:41 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> > wrote:
on Fri Jan 13 2017, John McCall <swift-evolution@swift.org> wrote:

Maybe not in the use case you're thinking of, though?

Ideally I'd like to be able to guide deduction to pick a sensible
default for T when there's insufficient type context, but that's a
separable feature.

Yes, defaulting would fix the usability problem.

John.

--
-Dave

I'm also not sure we'd ever want the element type to be inferred from
context like this. Generic subscripts as I see it are about being
generic over *indexes*, not somehow about presenting a polymorphic
value.

Actually I *would* want to be able to do that, though I admit it's the
1% case (or less).

Would you actually want the value type to be inferred, or you would
just want it to be allowed to vary according to the index type?
Because the former sounds like a huge usability issue.

Both. Usability-wise, it's no worse than f<T>() -> T, which has its
(rare) uses today and doesn't cause a problem when it's not used.

Well, I'm assuming you would like to be able to do things like call
mutating methods on these things.

Yes. That's already *possible* even without a default:

   func mutate<T, R>(_ x: inout T, applying body: (inout T)->R) -> R {
     return body(&x)
   }

   mutate(&thingWithGenericSubscript[3]) {
     (a: inout X)->() in a.mutatingMethod() // deduce X
   }

Obviously this is awful. The default mentioned below helps eliminate
the awfulness.

Right. I described it as a usability problem, not an expressiveness barrier. :)

But not all subscripts are, or need to be, get/set, and even without the
default, the feature would be useful with get-only subscripts.

True. And like I've said, it's possible that this isn't a big problem.

John.

···

On Jan 15, 2017, at 8:32 PM, Dave Abrahams <dabrahams@apple.com> wrote:
on Sun Jan 15 2017, John McCall <rjmccall-AT-apple.com> wrote:

On Jan 15, 2017, at 7:22 PM, Dave Abrahams <dabrahams@apple.com> wrote:
on Sun Jan 15 2017, John McCall <rjmccall-AT-apple.com> wrote:

On Jan 14, 2017, at 6:41 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> >> wrote:
on Fri Jan 13 2017, John McCall <swift-evolution@swift.org> wrote:

Maybe not in the use case you're thinking of, though?

Ideally I'd like to be able to guide deduction to pick a sensible
default for T when there's insufficient type context, but that's a
separable feature.

Yes, defaulting would fix the usability problem.

John.

--
-Dave

Where generic subscripts are concerned, there are a couple of different things to express:
- Generic parameter (I can understand various co-ordinates for the data)
- Generic return type (I can construct your preferred representation of the data)
- Generic setter type (I can set the data using various compatible types):

I think all of these should be expressed with a single generic signature on the subscript itself. The element type passed to the setter and returned from the getter should be the same IMO, otherwise it’s not clear how it will work.

Yes. It's quite important that any particular subscript reference is still a single consistent entity, even if generic; we would not want, say, a read-modify-write access to be able to somehow invoke the getter and setter at different generic arguments, or to traffic in different element types.

I'm also not sure we'd ever want the element type to be inferred from context like this. Generic subscripts as I see it are about being generic over *indexes*, not somehow about presenting a polymorphic value.

This is a consequence of your vision of subscript. If interesting, it is also limiting for no real purpose.

As the developer of a Swift database library, I'd like to offer a better API than the following:

    // Current state of affairs
    let name: String = row.value(named: "name")
    let bookCount: Int = row.value(named: "bookCount")
    let hasBooks: Bool = row.value(named: "bookCount")

Instead, I wish I could offer GRDB.swift would let its users write:

    // With improved subscripts
    let name: String = row["name"]
    let bookCount: Int = row["bookCount"]
    let hasBooks: Bool = row["bookCount"]

And this requires genericity on return type.

This is not typesafe at all if the type does not depend on the argument. I'd prefer keys carrying the meta information of their respective database column keeping the whole API typesafe.

As long as your personal preference has no impact on return-type genericity subscripts adoption, I'm fine with it :-)

No problem with that :-)

-Thorsten

···

Am 23.01.2017 um 18:26 schrieb Gwendal Roué <gwendal.roue@gmail.com>:

Gwendal