[Review] SE-0044 Import as Member


(Douglas Gregor) #1

Hello Swift community,

The review of SE-0044 “Import as Member" begins now and runs through March 22, 2016. The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0044-import-as-member.md <https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-proposal.md>
Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at

https://lists.swift.org/mailman/listinfo/swift-evolution
or, if you would like to keep your feedback private, directly to the review manager. When replying, please try to keep the proposal link at the top of the message:

Proposal link:

https://github.com/apple/swift-evolution/blob/master/proposals/0044-import-as-member.md <https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-proposal.md>
Reply text

Other replies
<https://github.com/apple/swift-evolution#what-goes-into-a-review-1>What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift. When writing your review, here are some questions you might want to answer in your review:

What is your evaluation of the proposal?
Is the problem being addressed significant enough to warrant a change to Swift?
Does this proposal fit well with the feel and direction of Swift?
If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
More information about the Swift evolution process is available at

https://github.com/apple/swift-evolution/blob/master/process.md
Thank you,

Doug Gregor

Review Manager


(Douglas Gregor) #2

Sigh. Real link here:

https://github.com/apple/swift-evolution/blob/master/proposals/0044-import-as-member.md

  - Doug

···

On Mar 15, 2016, at 9:31 AM, Douglas Gregor <dgregor@apple.com> wrote:

Hello Swift community,

The review of SE-0044 “Import as Member" begins now and runs through March 22, 2016. The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0044-import-as-member.md


(Karsten Bruns) #3

First link does not work.

···

On 15 Mar 2016, at 17:31, Douglas Gregor <dgregor@apple.com> wrote:

Hello Swift community,

The review of SE-0044 “Import as Member" begins now and runs through March 22, 2016. The proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0044-import-as-member.md <https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-proposal.md>
Reviews are an important part of the Swift evolution process. All reviews should be sent to the swift-evolution mailing list at

https://lists.swift.org/mailman/listinfo/swift-evolution
or, if you would like to keep your feedback private, directly to the review manager. When replying, please try to keep the proposal link at the top of the message:

Proposal link:

https://github.com/apple/swift-evolution/blob/master/proposals/0044-import-as-member.md <https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-proposal.md>
Reply text

Other replies
<https://github.com/apple/swift-evolution#what-goes-into-a-review-1>What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift. When writing your review, here are some questions you might want to answer in your review:

What is your evaluation of the proposal?
Is the problem being addressed significant enough to warrant a change to Swift?
Does this proposal fit well with the feel and direction of Swift?
If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
More information about the Swift evolution process is available at

https://github.com/apple/swift-evolution/blob/master/process.md
Thank you,

Doug Gregor

Review Manager

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


(Michel Fortin) #4

What is your evaluation of the proposal?

Looks like a very good idea. Less wrapper code means less possibility of an error, a less cluttered call stack when debugging, and faster compile times (because of less code).

It looks like it'll work well for importing Apple headers. I'm a bit worried however about what it'll do for APIs that have a different design or syntax conventions. What happens with this function for instance?

  int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);

Reading the proposal, it isn't all that clear where it stops. Does automatic inference work with snake-case? Should it? Does it import functions with unmanaged pointers in the first position as mutating methods? Hopefully not. Is this going to make some APIs seemingly inconsistent as to what becomes a member and what stays global? Probably. I can't tell really from reading the proposal.

Is the problem being addressed significant enough to warrant a change to Swift?

It makes code more readable, less alien in a Swift program, and by having less wrapper code it just makes everything simpler. I think that is an important improvement.

Does this proposal fit well with the feel and direction of Swift?

It fits very well with the path taken for renaming Objective-C methods to have more Swifty names. Swift 3 seems to be the right release for this change.

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

N/A

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Quick reading, then looked at some non-Apple C APIs trying to figure out what the automatic inference heuristics would do to them.

···

--
Michel Fortin
https://michelf.ca


(Brent Royal-Gordon) #5

  • What is your evaluation of the proposal?

Overall in favor.

I don't like the getter syntax:

  float Point3DGetRadius(Point3D point) __attribute__((swift_name("getter:Point3D.radius(self:)")));

I think we would be better off thinking of this instead as adding an accessor to a property, perhaps with a syntax along these lines:

  float Point3DGetRadius(Point3D point) __attribute__((swift_name("Point3D.radius.get(self:)")));

However, talking about operations-associated-with-a-property seems to be a common theme with the behaviors proposal; you may want to think about a syntax that could be used for both of them (and perhaps in demangling and diagnostics as well).

I also find it odd that this proposal doesn't address subscripts.

I assume that, on types imported as value types, Swift treats operations whose self parameter is a (non-const) pointer to the type as mutating and others as nonmutating. (This is not explicitly stated in the proposal, though.) However, it's not clear how Swift makes that initial determination of whether a type should be imported as a value type or a reference type.

Has this proposal's use against libdispatch been evaluated? I would love to see `dispatch_async(_:_:)` become `dispatch_queue.async(function:)`.

  • Is the problem being addressed significant enough to warrant a change to Swift?

Yes. Directly imported C APIs are a mess, and simple adapters are a pain to write. This substantially improves the situation.

  • Does this proposal fit well with the feel and direction of Swift?

Yes, it does. We seem to be pretty aggressively trying to improve bridging in this version, and this continues that theme.

  • If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

I haven't; bridging is universally terrible.

  • How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

A couple reads at various points.

···

--
Brent Royal-Gordon
Architechies


(Patrick Gili) #6

What is your evaluation of the proposal?

This is a well thought out proposal with many facets to simplify importing C libraries into Swift. I especially like the automatic inference heuristics.

Is the problem being addressed significant enough to warrant a change to Swift?

Yes.

Does this proposal fit well with the feel and direction of Swift?

Yes.

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

This would far excel what other languages support by way of importing, bridging, and wrapping.

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Thoroughly read the proposal.


(Michael Ilseman) #7

What is your evaluation of the proposal?

Looks like a very good idea. Less wrapper code means less possibility of an error, a less cluttered call stack when debugging, and faster compile times (because of less code).

It looks like it'll work well for importing Apple headers. I'm a bit worried however about what it'll do for APIs that have a different design or syntax conventions. What happens with this function for instance?

  int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);

Reading the proposal, it isn't all that clear where it stops. Does automatic inference work with snake-case? Should it? Does it import functions with unmanaged pointers in the first position as mutating methods? Hopefully not. Is this going to make some APIs seemingly inconsistent as to what becomes a member and what stays global? Probably. I can't tell really from reading the proposal.

There’s two things present in this proposal, manual annotation and automatic inference. Projects such as sqlite3 can use manual annotation, so that they can control their APIs and have a chance to import e.g. sqlite3_stmt_readonly as a member on a type (perhaps also named/defined otherwise, e.g. through existing attributes or other proposed elsewhere).

Automatic inference, at least in the near term, will not be turned on by default for all C APIs, but will start out as opt-in. In the near term, heuristics and techniques are tuned for CF-style naming conventions. Future work could be broadening this, and I think having something to also reason through snake_case is definitely possible. Future work could expand the inference system to have many more (configurable) heuristics, but that’s out of scope for this proposal. But, unless the project opts-in, the inference system will not try to infer how to import as a member.

Is the problem being addressed significant enough to warrant a change to Swift?

It makes code more readable, less alien in a Swift program, and by having less wrapper code it just makes everything simpler. I think that is an important improvement.

Does this proposal fit well with the feel and direction of Swift?

It fits very well with the path taken for renaming Objective-C methods to have more Swifty names. Swift 3 seems to be the right release for this change.

If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?

N/A

How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Quick reading, then looked at some non-Apple C APIs trying to figure out what the automatic inference heuristics would do to them.

I am very interested in improving non-Apple C APIs as well. I’m not sure how much will be in scope for Swift 3, though.

···

On Mar 15, 2016, at 5:12 PM, Michel Fortin via swift-evolution <swift-evolution@swift.org> wrote:

--
Michel Fortin
https://michelf.ca

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


(Michel Fortin) #8

That clarifies things and it makes perfect sense. Thanks. :slight_smile:

···

Le 15 mars 2016 à 20:31, Michael Ilseman <milseman@apple.com> a écrit :

Automatic inference, at least in the near term, will not be turned on by default for all C APIs, but will start out as opt-in. In the near term, heuristics and techniques are tuned for CF-style naming conventions. Future work could be broadening this, and I think having something to also reason through snake_case is definitely possible. Future work could expand the inference system to have many more (configurable) heuristics, but that’s out of scope for this proposal. But, unless the project opts-in, the inference system will not try to infer how to import as a member.

--
Michel Fortin
https://michelf.ca


(Douglas Gregor) #9

  • What is your evaluation of the proposal?

Overall in favor.

I don't like the getter syntax:

  float Point3DGetRadius(Point3D point) __attribute__((swift_name("getter:Point3D.radius(self:)")));

I think we would be better off thinking of this instead as adding an accessor to a property, perhaps with a syntax along these lines:

  float Point3DGetRadius(Point3D point) __attribute__((swift_name("Point3D.radius.get(self:)")));

However, talking about operations-associated-with-a-property seems to be a common theme with the behaviors proposal; you may want to think about a syntax that could be used for both of them (and perhaps in demangling and diagnostics as well).

FWIW, the “getter:” and “setter:” syntax was borrowed from the discussion of extending #selector to work with getters and setters of properties. Also, Point3D.radius.get could be a badly-named function “get” in a badly-named type “Point3D.radius” :wink:

I also find it odd that this proposal doesn't address subscripts.

Yeah. It should probably be a part of the proposal for completeness.

I assume that, on types imported as value types, Swift treats operations whose self parameter is a (non-const) pointer to the type as mutating and others as nonmutating. (This is not explicitly stated in the proposal, though.)

That’s correct. It’s in the implementation but not the proposal.

However, it's not clear how Swift makes that initial determination of whether a type should be imported as a value type or a reference type.

That’s actually orthogonal to this proposal. However, right now you have C enums and structs mapping to value types, CF types mapping to reference types, and ObjC classes and protocols mapping to reference types.

Has this proposal's use against libdispatch been evaluated? I would love to see `dispatch_async(_:_:)` become `dispatch_queue.async(function:)`.

IIRC, the heuristics didn’t work so well, but it should be possible to swift_name libdispatch.

  - Doug

···

On Mar 16, 2016, at 4:48 PM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:


(Michael Ilseman) #10

Thanks for pointing out the ambiguity! I added an amendment to the proposal in https://github.com/apple/swift-evolution/pull/214

···

On Mar 16, 2016, at 4:58 AM, Michel Fortin <michel.fortin@michelf.ca> wrote:

Le 15 mars 2016 à 20:31, Michael Ilseman <milseman@apple.com> a écrit :

Automatic inference, at least in the near term, will not be turned on by default for all C APIs, but will start out as opt-in. In the near term, heuristics and techniques are tuned for CF-style naming conventions. Future work could be broadening this, and I think having something to also reason through snake_case is definitely possible. Future work could expand the inference system to have many more (configurable) heuristics, but that’s out of scope for this proposal. But, unless the project opts-in, the inference system will not try to infer how to import as a member.

That clarifies things and it makes perfect sense. Thanks. :slight_smile:

--
Michel Fortin
https://michelf.ca


(Michael Ilseman) #11

  • What is your evaluation of the proposal?

Overall in favor.

I don't like the getter syntax:

  float Point3DGetRadius(Point3D point) __attribute__((swift_name("getter:Point3D.radius(self:)")));

I think we would be better off thinking of this instead as adding an accessor to a property, perhaps with a syntax along these lines:

  float Point3DGetRadius(Point3D point) __attribute__((swift_name("Point3D.radius.get(self:)")));

However, talking about operations-associated-with-a-property seems to be a common theme with the behaviors proposal; you may want to think about a syntax that could be used for both of them (and perhaps in demangling and diagnostics as well).

FWIW, the “getter:” and “setter:” syntax was borrowed from the discussion of extending #selector to work with getters and setters of properties. Also, Point3D.radius.get could be a badly-named function “get” in a badly-named type “Point3D.radius” :wink:

I also find it odd that this proposal doesn't address subscripts.

Yeah. It should probably be a part of the proposal for completeness.

I assume that, on types imported as value types, Swift treats operations whose self parameter is a (non-const) pointer to the type as mutating and others as nonmutating. (This is not explicitly stated in the proposal, though.)

That’s correct. It’s in the implementation but not the proposal.

However, it's not clear how Swift makes that initial determination of whether a type should be imported as a value type or a reference type.

That’s actually orthogonal to this proposal. However, right now you have C enums and structs mapping to value types, CF types mapping to reference types, and ObjC classes and protocols mapping to reference types.

Has this proposal's use against libdispatch been evaluated? I would love to see `dispatch_async(_:_:)` become `dispatch_queue.async(function:)`.

IIRC, the heuristics didn’t work so well, but it should be possible to swift_name lib dispatch.

swift_name is very useful for libDispatch and is showing success, so the manual annotation portion of this proposal fits very well. The inference heuristics are currently not tuned well for libDispatch, and adjusting them is probably future work. In the mean time, manual annotation in the C API is not too burdensome and a definite improvement over overlays.

···

On Mar 16, 2016, at 9:53 PM, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

On Mar 16, 2016, at 4:48 PM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

  - Doug

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


(Michael Ilseman) #12

  • What is your evaluation of the proposal?

Overall in favor.

I don't like the getter syntax:

  float Point3DGetRadius(Point3D point) __attribute__((swift_name("getter:Point3D.radius(self:)")));

I think we would be better off thinking of this instead as adding an accessor to a property, perhaps with a syntax along these lines:

  float Point3DGetRadius(Point3D point) __attribute__((swift_name("Point3D.radius.get(self:)")));

However, talking about operations-associated-with-a-property seems to be a common theme with the behaviors proposal; you may want to think about a syntax that could be used for both of them (and perhaps in demangling and diagnostics as well).

FWIW, the “getter:” and “setter:” syntax was borrowed from the discussion of extending #selector to work with getters and setters of properties. Also, Point3D.radius.get could be a badly-named function “get” in a badly-named type “Point3D.radius” :wink:

I also find it odd that this proposal doesn't address subscripts.

Yeah. It should probably be a part of the proposal for completeness.

For subscripts, I have 3 alternatives below to consider, ordered in my personal list of preference. Which seems to make the most sense?
1.

// Import as subscript
float Point3DGetPointAtIndex(int idx, Point3D point)
__attribute__((swift_name("getter:subscript(index:self:)")))
void Point3DSetPointAtIndex(int idx, Point3D point, float val)
__attribute__((swift_name("getter:subscript(index:self:_:)")))
2.

// Import as subscript
float Point3DGetPointAtIndex(int idx, Point3D point)
__attribute__((swift_name("getter:subscript(_:self:)")))
void Point3DSetPointAtIndex(int idx, Point3D point, float val)
__attribute__((swift_name("getter:subscript(_:self:newValue:)")))
3.

// Import as subscript
float Point3DGetPointAtIndex(int idx, Point3D point)
__attribute__((swift_name("getter:subscript(index:self:)")))
void Point3DSetPointAtIndex(int idx, Point3D point, float val)
__attribute__((swift_name("getter:subscript(index:self:newValue:)")))

···

On Mar 17, 2016, at 11:45 AM, Michael Ilseman via swift-evolution <swift-evolution@swift.org> wrote:

On Mar 16, 2016, at 9:53 PM, Douglas Gregor via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Mar 16, 2016, at 4:48 PM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I assume that, on types imported as value types, Swift treats operations whose self parameter is a (non-const) pointer to the type as mutating and others as nonmutating. (This is not explicitly stated in the proposal, though.)

That’s correct. It’s in the implementation but not the proposal.

However, it's not clear how Swift makes that initial determination of whether a type should be imported as a value type or a reference type.

That’s actually orthogonal to this proposal. However, right now you have C enums and structs mapping to value types, CF types mapping to reference types, and ObjC classes and protocols mapping to reference types.

Has this proposal's use against libdispatch been evaluated? I would love to see `dispatch_async(_:_:)` become `dispatch_queue.async(function:)`.

IIRC, the heuristics didn’t work so well, but it should be possible to swift_name lib dispatch.

swift_name is very useful for libDispatch and is showing success, so the manual annotation portion of this proposal fits very well. The inference heuristics are currently not tuned well for libDispatch, and adjusting them is probably future work. In the mean time, manual annotation in the C API is not too burdensome and a definite improvement over overlays.

  - Doug

_______________________________________________
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


(Michael Ilseman) #13

Another amendment, I’m looking into importing onto protocols as well. But, protocols are going to have to be considerably more constrained, in that only “instance” members are supported. Static members and inits will have to be forbidden. Since the instance members will come in as members of a protocol extension, they remain static dispatch and off of the protocol type.

When we figure out subscript, I’ll amend the proposal to call these out.

···

On Mar 22, 2016, at 5:21 PM, Michael Ilseman <milseman@apple.com> wrote:

On Mar 17, 2016, at 11:45 AM, Michael Ilseman via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Mar 16, 2016, at 9:53 PM, Douglas Gregor via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Mar 16, 2016, at 4:48 PM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

  • What is your evaluation of the proposal?

Overall in favor.

I don't like the getter syntax:

  float Point3DGetRadius(Point3D point) __attribute__((swift_name("getter:Point3D.radius(self:)")));

I think we would be better off thinking of this instead as adding an accessor to a property, perhaps with a syntax along these lines:

  float Point3DGetRadius(Point3D point) __attribute__((swift_name("Point3D.radius.get(self:)")));

However, talking about operations-associated-with-a-property seems to be a common theme with the behaviors proposal; you may want to think about a syntax that could be used for both of them (and perhaps in demangling and diagnostics as well).

FWIW, the “getter:” and “setter:” syntax was borrowed from the discussion of extending #selector to work with getters and setters of properties. Also, Point3D.radius.get could be a badly-named function “get” in a badly-named type “Point3D.radius” :wink:

I also find it odd that this proposal doesn't address subscripts.

Yeah. It should probably be a part of the proposal for completeness.

For subscripts, I have 3 alternatives below to consider, ordered in my personal list of preference. Which seems to make the most sense?
1.

// Import as subscript
float Point3DGetPointAtIndex(int idx, Point3D point)
__attribute__((swift_name("getter:subscript(index:self:)")))
void Point3DSetPointAtIndex(int idx, Point3D point, float val)
__attribute__((swift_name("getter:subscript(index:self:_:)")))
2.

// Import as subscript
float Point3DGetPointAtIndex(int idx, Point3D point)
__attribute__((swift_name("getter:subscript(_:self:)")))
void Point3DSetPointAtIndex(int idx, Point3D point, float val)
__attribute__((swift_name("getter:subscript(_:self:newValue:)")))
3.

// Import as subscript
float Point3DGetPointAtIndex(int idx, Point3D point)
__attribute__((swift_name("getter:subscript(index:self:)")))
void Point3DSetPointAtIndex(int idx, Point3D point, float val)
__attribute__((swift_name("getter:subscript(index:self:newValue:)")))

I assume that, on types imported as value types, Swift treats operations whose self parameter is a (non-const) pointer to the type as mutating and others as nonmutating. (This is not explicitly stated in the proposal, though.)

That’s correct. It’s in the implementation but not the proposal.

However, it's not clear how Swift makes that initial determination of whether a type should be imported as a value type or a reference type.

That’s actually orthogonal to this proposal. However, right now you have C enums and structs mapping to value types, CF types mapping to reference types, and ObjC classes and protocols mapping to reference types.

Has this proposal's use against libdispatch been evaluated? I would love to see `dispatch_async(_:_:)` become `dispatch_queue.async(function:)`.

IIRC, the heuristics didn’t work so well, but it should be possible to swift_name lib dispatch.

swift_name is very useful for libDispatch and is showing success, so the manual annotation portion of this proposal fits very well. The inference heuristics are currently not tuned well for libDispatch, and adjusting them is probably future work. In the mean time, manual annotation in the C API is not too burdensome and a definite improvement over overlays.

  - Doug

_______________________________________________
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


(Jordan Rose) #14

Do any of these allow you to put labels on the imported subscript indices? I would expect the declaration in #3 to come through as (the completely legal Swift code):

subscript(index index: CInt) -> CFloat

which you would then use as

myPoint[index: 0]

(Clarification for anyone following along: it's important to be able to distinguish the index parameter from the new value, which we wouldn't want to hardcode the order of. We also wouldn't want to have to look up the getter to figure it out.)

I'd rather not claim 'newValue' as a magic name, but I don't see a good alternative. So my vote is for #2.

Jordan

···

On Mar 22, 2016, at 17:21, Michael Ilseman via swift-evolution <swift-evolution@swift.org> wrote:

On Mar 17, 2016, at 11:45 AM, Michael Ilseman via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Mar 16, 2016, at 9:53 PM, Douglas Gregor via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Mar 16, 2016, at 4:48 PM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

  • What is your evaluation of the proposal?

Overall in favor.

I don't like the getter syntax:

  float Point3DGetRadius(Point3D point) __attribute__((swift_name("getter:Point3D.radius(self:)")));

I think we would be better off thinking of this instead as adding an accessor to a property, perhaps with a syntax along these lines:

  float Point3DGetRadius(Point3D point) __attribute__((swift_name("Point3D.radius.get(self:)")));

However, talking about operations-associated-with-a-property seems to be a common theme with the behaviors proposal; you may want to think about a syntax that could be used for both of them (and perhaps in demangling and diagnostics as well).

FWIW, the “getter:” and “setter:” syntax was borrowed from the discussion of extending #selector to work with getters and setters of properties. Also, Point3D.radius.get could be a badly-named function “get” in a badly-named type “Point3D.radius” :wink:

I also find it odd that this proposal doesn't address subscripts.

Yeah. It should probably be a part of the proposal for completeness.

For subscripts, I have 3 alternatives below to consider, ordered in my personal list of preference. Which seems to make the most sense?
1.

// Import as subscript
float Point3DGetPointAtIndex(int idx, Point3D point)
__attribute__((swift_name("getter:subscript(index:self:)")))
void Point3DSetPointAtIndex(int idx, Point3D point, float val)
__attribute__((swift_name("getter:subscript(index:self:_:)")))
2.

// Import as subscript
float Point3DGetPointAtIndex(int idx, Point3D point)
__attribute__((swift_name("getter:subscript(_:self:)")))
void Point3DSetPointAtIndex(int idx, Point3D point, float val)
__attribute__((swift_name("getter:subscript(_:self:newValue:)")))
3.

// Import as subscript
float Point3DGetPointAtIndex(int idx, Point3D point)
__attribute__((swift_name("getter:subscript(index:self:)")))
void Point3DSetPointAtIndex(int idx, Point3D point, float val)
__attribute__((swift_name("getter:subscript(index:self:newValue:)")))


(Brent Royal-Gordon) #15

float Point3DGetPointAtIndex(int idx, Point3D point)
__attribute__((swift_name("getter:subscript(_:self:)")))
void Point3DSetPointAtIndex(int idx, Point3D point, float val)
__attribute__((swift_name("getter:subscript(_:self:newValue:)")))

I think this is the best option. Subscripts can have multiple parameters, including parameter labels, so you need the full range of expressiveness, including `_`, to correctly represent them. `newValue`'s name is technically changeable, but it almost never actually *is* changed, and everyone will understand what it refers to.

···

--
Brent Royal-Gordon
Architechies


(Michael Ilseman) #16

  • What is your evaluation of the proposal?

Overall in favor.

I don't like the getter syntax:

  float Point3DGetRadius(Point3D point) __attribute__((swift_name("getter:Point3D.radius(self:)")));

I think we would be better off thinking of this instead as adding an accessor to a property, perhaps with a syntax along these lines:

  float Point3DGetRadius(Point3D point) __attribute__((swift_name("Point3D.radius.get(self:)")));

However, talking about operations-associated-with-a-property seems to be a common theme with the behaviors proposal; you may want to think about a syntax that could be used for both of them (and perhaps in demangling and diagnostics as well).

FWIW, the “getter:” and “setter:” syntax was borrowed from the discussion of extending #selector to work with getters and setters of properties. Also, Point3D.radius.get could be a badly-named function “get” in a badly-named type “Point3D.radius” :wink:

I also find it odd that this proposal doesn't address subscripts.

Yeah. It should probably be a part of the proposal for completeness.

For subscripts, I have 3 alternatives below to consider, ordered in my personal list of preference. Which seems to make the most sense?
1.

// Import as subscript
float Point3DGetPointAtIndex(int idx, Point3D point)
__attribute__((swift_name("getter:subscript(index:self:)")))
void Point3DSetPointAtIndex(int idx, Point3D point, float val)
__attribute__((swift_name("getter:subscript(index:self:_:)")))
2.

// Import as subscript
float Point3DGetPointAtIndex(int idx, Point3D point)
__attribute__((swift_name("getter:subscript(_:self:)")))
void Point3DSetPointAtIndex(int idx, Point3D point, float val)
__attribute__((swift_name("getter:subscript(_:self:newValue:)")))
3.

// Import as subscript
float Point3DGetPointAtIndex(int idx, Point3D point)
__attribute__((swift_name("getter:subscript(index:self:)")))
void Point3DSetPointAtIndex(int idx, Point3D point, float val)
__attribute__((swift_name("getter:subscript(index:self:newValue:)")))

Do any of these allow you to put labels on the imported subscript indices? I would expect the declaration in #3 to come through as (the completely legal Swift code):

Prior to this, anything that wasn’t “self” would be treated as an argument label. That is, you couldn’t (via current syntax) name an argument label “self”. Now, because subscript’s setter requires two specific parameters in addition to self, we need to special-case another word, either “index” or “newValue” (or both).

I don’t really like any of these solutions. How about changing swift_name’s special label syntax? Something to denote the specialness of self/newValue? Then we could go with option 2.

__attribute__((swift_name("Type.foo(@self:otherParam:")));
__attribute__((swift_name("Type.foo({self}:otherParam:")));
__attribute__((swift_name("Type.foo(<self>:otherParam:")));
__attribute__((swift_name("Type.foo([self]:otherParam:")));
__attribute__((swift_name("Type.foo(`self`:otherParam:")));
__attribute__((swift_name("setter:Type.subscript(`self`:_:`newValue`")));

Any ideas?

···

On Mar 22, 2016, at 6:03 PM, Jordan Rose <jordan_rose@apple.com> wrote:

On Mar 22, 2016, at 17:21, Michael Ilseman via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Mar 17, 2016, at 11:45 AM, Michael Ilseman via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Mar 16, 2016, at 9:53 PM, Douglas Gregor via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Mar 16, 2016, at 4:48 PM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

subscript(index index: CInt) -> CFloat

which you would then use as

myPoint[index: 0]

(Clarification for anyone following along: it's important to be able to distinguish the index parameter from the new value, which we wouldn't want to hardcode the order of. We also wouldn't want to have to look up the getter to figure it out.)

I'd rather not claim 'newValue' as a magic name, but I don't see a good alternative. So my vote is for #2.

Jordan


(Douglas Gregor) #17

Right. And at worse we’ve eliminated the ability to express

subscript (newValue newValue: Int) -> Int { … }

I can live with that limitation.

  - Doug

···

On Mar 22, 2016, at 9:30 PM, Brent Royal-Gordon <brent@architechies.com> wrote:

float Point3DGetPointAtIndex(int idx, Point3D point)
__attribute__((swift_name("getter:subscript(_:self:)")))
void Point3DSetPointAtIndex(int idx, Point3D point, float val)
__attribute__((swift_name("getter:subscript(_:self:newValue:)")))

I think this is the best option. Subscripts can have multiple parameters, including parameter labels, so you need the full range of expressiveness, including `_`, to correctly represent them. `newValue`'s name is technically changeable, but it almost never actually *is* changed, and everyone will understand what it refers to.


(Michael Ilseman) #18

Updated proposal with https://github.com/apple/swift-evolution/pull/226

I went with option #2 as recommended.

···

On Mar 23, 2016, at 10:27 AM, Douglas Gregor <dgregor@apple.com> wrote:

On Mar 22, 2016, at 9:30 PM, Brent Royal-Gordon <brent@architechies.com <mailto:brent@architechies.com>> wrote:

float Point3DGetPointAtIndex(int idx, Point3D point)
__attribute__((swift_name("getter:subscript(_:self:)")))
void Point3DSetPointAtIndex(int idx, Point3D point, float val)
__attribute__((swift_name("getter:subscript(_:self:newValue:)")))

I think this is the best option. Subscripts can have multiple parameters, including parameter labels, so you need the full range of expressiveness, including `_`, to correctly represent them. `newValue`'s name is technically changeable, but it almost never actually *is* changed, and everyone will understand what it refers to.

Right. And at worse we’ve eliminated the ability to express

subscript (newValue newValue: Int) -> Int { … }

I can live with that limitation.

  - Doug