Change subscripts to use colons

Subscripts are a hybrid of properties and functions, since they have a parameter list, as well as getters and setters, so use of either symbol will be unusual in this case.

However, I think a colon is more suitable, since it implies the possibility to set the value.

In the future, if we add throwing getters/ setters:

subscript(_ position: Int) -> Element {
    get {
        return …
   }
   throwing set {
        …
    }
}

Should this require ‘throws -> Element’? Using a colon also removes this potentially confusing case.

Thoughts?

Can you show us an example of the current syntax and your proposed replacement? I'm not sure what you actually mean by "use colons".

···

On Jul 9, 2016, at 11:48 AM, James Froggatt via swift-evolution <swift-evolution@swift.org> wrote:

Subscripts are a hybrid of properties and functions, since they have a parameter list, as well as getters and setters, so use of either symbol will be unusual in this case.

However, I think a colon is more suitable, since it implies the possibility to set the value.

--
Brent Royal-Gordon
Architechies

Slightly related to this, I would really love to have non-subscript parameterized properties. It would allow us to write

button.image(for: .normal) = image

instead of

button.setImage(image, for: .normal)

The same can be achieved through subscripts, but it’s not always as nice. It would bring subscripts and computed properties closer together, which also seems to be the goal of your proposal. Perhaps the two ideas could be combined?

···

Subscripts are a hybrid of properties and functions, since they have a parameter list, as well as getters and setters, so use of either symbol will be unusual in this case.

However, I think a colon is more suitable, since it implies the possibility to set the value.

In the future, if we add throwing getters/ setters:

subscript(_ position: Int) ->Element {
get {
return …
}
throwing set {

}
}

Should this require ‘throws ->Element’? Using a colon also removes this potentially confusing case.

Thoughts?

Currently, the signature is:
subscript(_ example: Int) -> Element {
    get { … }
    set { … }
}

The alternative, using a colon, would be:
subscript(_ example: Int) : Element {
    get { … }
    set { … }
}

Sorry if that wasn't clear.

This would be to better reflect the property-like nature of access.

From James F

···

On 10 Jul 2016, at 23:57, Brent Royal-Gordon <brent@architechies.com> wrote:

On Jul 9, 2016, at 11:48 AM, James Froggatt via swift-evolution <swift-evolution@swift.org> wrote:

Subscripts are a hybrid of properties and functions, since they have a parameter list, as well as getters and setters, so use of either symbol will be unusual in this case.

However, I think a colon is more suitable, since it implies the possibility to set the value.

Can you show us an example of the current syntax and your proposed replacement? I'm not sure what you actually mean by "use colons".

--
Brent Royal-Gordon
Architechies

When would you want to use this instead of something like `button[imageFor:
.normal]` ?

···

On Mon, Jul 11, 2016 at 3:00 PM, Tim Vermeulen via swift-evolution < swift-evolution@swift.org> wrote:

Slightly related to this, I would really love to have non-subscript
parameterized properties. It would allow us to write

button.image(for: .normal) = image

instead of

button.setImage(image, for: .normal)

The same can be achieved through subscripts, but it’s not always as nice.
It would bring subscripts and computed properties closer together, which
also seems to be the goal of your proposal. Perhaps the two ideas could be
combined?

> Subscripts are a hybrid of properties and functions, since they have a
parameter list, as well as getters and setters, so use of either symbol
will be unusual in this case.
>
> However, I think a colon is more suitable, since it implies the
possibility to set the value.
>
>
> In the future, if we add throwing getters/ setters:
>
> subscript(_ position: Int) ->Element {
> get {
> return …
> }
> throwing set {
> …
> }
> }
>
> Should this require ‘throws ->Element’? Using a colon also removes this
potentially confusing case.
>
>
> Thoughts?
>
>
>

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

When would you want to use this instead of something like `button[imageFor: .normal]` ?

All the time, basically. Primarily because IMO it doesn’t really make sense to make “image” part of the argument label for the control state - we just have to (using subscripts) because subscripts themselves can’t be named. I think most people would agree that

let image = button.image(for: .normal)

is more readable than

let image = button[imageFor: .normal]

and likewise, I would prefer

button.image(for: .normal) = image

over

button[imageFor: .normal] = image

···

On 12 Jul 2016, at 00:20, Jacob Bandes-Storch <jtbandes@gmail.com> wrote:

On Mon, Jul 11, 2016 at 3:00 PM, Tim Vermeulen via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Slightly related to this, I would really love to have non-subscript parameterized properties. It would allow us to write

button.image(for: .normal) = image

instead of

button.setImage(image, for: .normal)

The same can be achieved through subscripts, but it’s not always as nice. It would bring subscripts and computed properties closer together, which also seems to be the goal of your proposal. Perhaps the two ideas could be combined?

> Subscripts are a hybrid of properties and functions, since they have a parameter list, as well as getters and setters, so use of either symbol will be unusual in this case.
>
> However, I think a colon is more suitable, since it implies the possibility to set the value.
>
>
> In the future, if we add throwing getters/ setters:
>
> subscript(_ position: Int) ->Element {
> get {
> return …
> }
> throwing set {
> …
> }
> }
>
> Should this require ‘throws ->Element’? Using a colon also removes this potentially confusing case.
>
>
> Thoughts?
>
>
>

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

I like the idea of ‘named parameterised properties’, but I don't see it happening for Swift 3, which is unfortunate since it would tidy up quite a few APIs.
If this feature does get added, updating getter functions to them would be a non-breaking change, so maybe it would be possible to deprecate setImage(_:for:) and have a long trasition period.

The idea of using subscripts for this kind of property is interesting, but currently they don't show up in autocomplete, so working with labelled subscripts is tricky.

This does raise the question of where to draw the line with subscripts - should they only be used where the container itself is the base name of the ‘function’? But if this is the case:

self.items[0 ... 1] //good

self.item[0] //good

self.items[0] //bad, reads as ‘items 0’, not the grammatical term ‘item 0’

You could say we're already misusing them.

···

On 11 Jul 2016, at 23:00, Tim Vermeulen <tvermeulen@me.com> wrote:

Slightly related to this, I would really love to have non-subscript parameterized properties. It would allow us to write

button.image(for: .normal) = image

instead of

button.setImage(image, for: .normal)

The same can be achieved through subscripts, but it’s not always as nice. It would bring subscripts and computed properties closer together, which also seems to be the goal of your proposal. Perhaps the two ideas could be combined?

> Subscripts are a hybrid of properties and functions, since they have a parameter list, as well as getters and setters, so use of either symbol will be unusual in this case.
>
> However, I think a colon is more suitable, since it implies the possibility to set the value.
>
>
> In the future, if we add throwing getters/ setters:
>
> subscript(_ position: Int) ->Element {
> get {
> return …
> }
> throwing set {
> …
> }
> }
>
> Should this require ‘throws ->Element’? Using a colon also removes this potentially confusing case.
>
>
> Thoughts?
>
>
>

+1, seems right to me. The original email wasn't clear to me, but this
example is.

FWIW, as a user of the language I'd hope that throwing subscript
getters/setters would be written "set throws { ... }" and/or "set(newValue)
throws { ... }" rather than "throwing set { ... }", for consistency with
function bodies.

...and now that I'm thinking about it, I'm almost tempted to recommend
"subscript[_ example: Int]: Element". Is that too crazy?

Jacob

···

On Sun, Jul 10, 2016 at 4:18 PM, James Froggatt via swift-evolution < swift-evolution@swift.org> wrote:

Currently, the signature is:
subscript(_ example: Int) -> Element {
    get { … }
    set { … }
}

The alternative, using a colon, would be:
subscript(_ example: Int) : Element {
    get { … }
    set { … }
}

Sorry if that wasn't clear.

This would be to better reflect the property-like nature of access.

From James F

On 10 Jul 2016, at 23:57, Brent Royal-Gordon <brent@architechies.com> > wrote:

>> On Jul 9, 2016, at 11:48 AM, James Froggatt via swift-evolution < > swift-evolution@swift.org> wrote:
>>
>> Subscripts are a hybrid of properties and functions, since they have a
parameter list, as well as getters and setters, so use of either symbol
will be unusual in this case.
>>
>> However, I think a colon is more suitable, since it implies the
possibility to set the value.
>
> Can you show us an example of the current syntax and your proposed
replacement? I'm not sure what you actually mean by "use colons".
>
> --
> Brent Royal-Gordon
> Architechies
>
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

But isn't it the getter and setter which are really function-y? That's why
you can write "set(myVariableName) { ... }"

···

On Sun, Jul 10, 2016 at 10:42 PM, Erica Sadun via swift-evolution < swift-evolution@swift.org> wrote:

> On Jul 10, 2016, at 5:18 PM, James Froggatt via swift-evolution < > swift-evolution@swift.org> wrote:
>
> Currently, the signature is:
> subscript(_ example: Int) -> Element {
> get { … }
> set { … }
> }
>
> The alternative, using a colon, would be:
> subscript(_ example: Int) : Element {
> get { … }
> set { … }
> }
>
> Sorry if that wasn't clear.
>
> This would be to better reflect the property-like nature of access.

It all depends on whether a subscript is more function-y or property-y,
and don't forget subscripts can take parameters and labels.

let y = myArrayOfStrings[safeIndex: 2, fallback: "foo"]

-- E

It all depends on whether a subscript is more function-y or property-y, and don't forget subscripts can take parameters and labels.

let y = myArrayOfStrings[safeIndex: 2, fallback: "foo"]

-- E

···

On Jul 10, 2016, at 5:18 PM, James Froggatt via swift-evolution <swift-evolution@swift.org> wrote:

Currently, the signature is:
subscript(_ example: Int) -> Element {
   get { … }
   set { … }
}

The alternative, using a colon, would be:
subscript(_ example: Int) : Element {
   get { … }
   set { … }
}

Sorry if that wasn't clear.

This would be to better reflect the property-like nature of access.

If I had to choose what subscripts are most like, I'd have to say properties. Subscripts don't support partial application, and do support setters. I agree with Patrick in that subscripts are more like a ‘parameterized property’.

If everyone's in favour, I'd like to get a proposal submitted for this. I can have a go when I have some time, though I'm not yet familiar with the process. If anyone with experience wants to take this on, that'd be a great help. I think the change in question is pretty straightforward.

From James F

···

On 11 Jul 2016, at 06:42, Erica Sadun <erica@ericasadun.com> wrote:

On Jul 10, 2016, at 5:18 PM, James Froggatt via swift-evolution <swift-evolution@swift.org> wrote:

Currently, the signature is:
subscript(_ example: Int) -> Element {
  get { … }
  set { … }
}

The alternative, using a colon, would be:
subscript(_ example: Int) : Element {
  get { … }
  set { … }
}

Sorry if that wasn't clear.

This would be to better reflect the property-like nature of access.

It all depends on whether a subscript is more function-y or property-y, and don't forget subscripts can take parameters and labels.

let y = myArrayOfStrings[safeIndex: 2, fallback: "foo"]

-- E

Good point. A subscript basically a parameterized property, not a function.
I'm in favor.

···

On Mon, Jul 11, 2016 at 9:18 AM, James Froggatt via swift-evolution < swift-evolution@swift.org> wrote:

Currently, the signature is:
subscript(_ example: Int) -> Element {
    get { … }
    set { … }
}

The alternative, using a colon, would be:
subscript(_ example: Int) : Element {
    get { … }
    set { … }
}

Sorry if that wasn't clear.

This would be to better reflect the property-like nature of access.

From James F

On 10 Jul 2016, at 23:57, Brent Royal-Gordon <brent@architechies.com> > wrote:

>> On Jul 9, 2016, at 11:48 AM, James Froggatt via swift-evolution < > swift-evolution@swift.org> wrote:
>>
>> Subscripts are a hybrid of properties and functions, since they have a
parameter list, as well as getters and setters, so use of either symbol
will be unusual in this case.
>>
>> However, I think a colon is more suitable, since it implies the
possibility to set the value.
>
> Can you show us an example of the current syntax and your proposed
replacement? I'm not sure what you actually mean by "use colons".
>
> --
> Brent Royal-Gordon
> Architechies
>
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

How about a proposal for named subscripts?

button.image[for: .normal] = image

defined using:

subscript image(for: UIControlState): UIImage? {
  get { … }
  set { … }
}

···

On 12 Jul 2016, at 00:29, Tim Vermeulen via swift-evolution <swift-evolution@swift.org> wrote:

On 12 Jul 2016, at 00:20, Jacob Bandes-Storch <jtbandes@gmail.com <mailto:jtbandes@gmail.com>> wrote:

When would you want to use this instead of something like `button[imageFor: .normal]` ?

All the time, basically. Primarily because IMO it doesn’t really make sense to make “image” part of the argument label for the control state - we just have to (using subscripts) because subscripts themselves can’t be named. I think most people would agree that

let image = button.image(for: .normal)

is more readable than

let image = button[imageFor: .normal]

and likewise, I would prefer

button.image(for: .normal) = image

over

button[imageFor: .normal] = image

On Mon, Jul 11, 2016 at 3:00 PM, Tim Vermeulen via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Slightly related to this, I would really love to have non-subscript parameterized properties. It would allow us to write

button.image(for: .normal) = image

instead of

button.setImage(image, for: .normal)

The same can be achieved through subscripts, but it’s not always as nice. It would bring subscripts and computed properties closer together, which also seems to be the goal of your proposal. Perhaps the two ideas could be combined?

> Subscripts are a hybrid of properties and functions, since they have a parameter list, as well as getters and setters, so use of either symbol will be unusual in this case.
>
> However, I think a colon is more suitable, since it implies the possibility to set the value.
>
>
> In the future, if we add throwing getters/ setters:
>
> subscript(_ position: Int) ->Element {
> get {
> return …
> }
> throwing set {
> …
> }
> }
>
> Should this require ‘throws ->Element’? Using a colon also removes this potentially confusing case.
>
>
> Thoughts?
>
>
>

_______________________________________________
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
https://lists.swift.org/mailman/listinfo/swift-evolution

I wasn’t suggesting named subscripts :) As you seem to have figured out, that gets confusing pretty quickly. Writing `self.items[0 ... 1]` seems a bit silly because the use of a subscript already implies items of some kind. So, to be clear, I was suggesting computed properties that allow parameters in round brackets, not in square brackets.

I agree that this might not make Swift 3, but your proposal already brings subscripts and computed properties closer together. What I’m suggesting is to make their declarations equivalent apart from `subscript` vs `var <variableName>`. As an example, this is what you’re proposing:

struct ArrayWrapper<Element> {
    var array: [Element]
    
    subscript(index: Int): Element {
        get { return array[index] }
        set { array[index] = newValue }
    }
}

and my suggestion would allow this:

extension ArrayWrapper {
    var element(at index: Int): Element {
        get { return array[index] }
        set { array[index] = newValue }
    }
}

var wrapper = ArrayWrapper(array: [1, 2, 3])
wrapper.element(at: 1) = 5
print(wrapper.array) // [1, 5, 3]

···

On 12 Jul 2016, at 11:24, James Froggatt <james.froggatt@me.com> wrote:

I like the idea of ‘named parameterised properties’, but I don't see it happening for Swift 3, which is unfortunate since it would tidy up quite a few APIs.
If this feature does get added, updating getter functions to them would be a non-breaking change, so maybe it would be possible to deprecate setImage(_:for:) and have a long trasition period.

The idea of using subscripts for this kind of property is interesting, but currently they don't show up in autocomplete, so working with labelled subscripts is tricky.

This does raise the question of where to draw the line with subscripts - should they only be used where the container itself is the base name of the ‘function’? But if this is the case:

self.items[0 ... 1] //good

self.item[0] //good

self.items[0] //bad, reads as ‘items 0’, not the grammatical term ‘item 0’

You could say we're already misusing them.

On 11 Jul 2016, at 23:00, Tim Vermeulen <tvermeulen@me.com <mailto:tvermeulen@me.com>> wrote:

Slightly related to this, I would really love to have non-subscript parameterized properties. It would allow us to write

button.image(for: .normal) = image

instead of

button.setImage(image, for: .normal)

The same can be achieved through subscripts, but it’s not always as nice. It would bring subscripts and computed properties closer together, which also seems to be the goal of your proposal. Perhaps the two ideas could be combined?

> Subscripts are a hybrid of properties and functions, since they have a parameter list, as well as getters and setters, so use of either symbol will be unusual in this case.
>
> However, I think a colon is more suitable, since it implies the possibility to set the value.
>
>
> In the future, if we add throwing getters/ setters:
>
> subscript(_ position: Int) ->Element {
> get {
> return …
> }
> throwing set {
> …
> }
> }
>
> Should this require ‘throws ->Element’? Using a colon also removes this potentially confusing case.
>
>
> Thoughts?
>
>
>

+1 as well. It always feels a little weird to be writing a setter inside
something that says it returns what should be the argument.

···

On Mon, Jul 11, 2016 at 00:05 Patrick Pijnappel via swift-evolution < swift-evolution@swift.org> wrote:

Good point. A subscript basically a parameterized property, not a
function. I'm in favor.

On Mon, Jul 11, 2016 at 9:18 AM, James Froggatt via swift-evolution < > swift-evolution@swift.org> wrote:

Currently, the signature is:
subscript(_ example: Int) -> Element {
    get { … }
    set { … }
}

The alternative, using a colon, would be:
subscript(_ example: Int) : Element {
    get { … }
    set { … }
}

Sorry if that wasn't clear.

This would be to better reflect the property-like nature of access.

From James F

On 10 Jul 2016, at 23:57, Brent Royal-Gordon <brent@architechies.com> >> wrote:

>> On Jul 9, 2016, at 11:48 AM, James Froggatt via swift-evolution < >> swift-evolution@swift.org> wrote:
>>
>> Subscripts are a hybrid of properties and functions, since they have a
parameter list, as well as getters and setters, so use of either symbol
will be unusual in this case.
>>
>> However, I think a colon is more suitable, since it implies the
possibility to set the value.
>
> Can you show us an example of the current syntax and your proposed
replacement? I'm not sure what you actually mean by "use colons".
>
> --
> 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

FWIW, we actually tried this at one point with exactly this rationale, but pulled it back out. In short, subscript decls are half way between func decls and var decls. Reasonable arguments can be made to align with either of them, but arrow “looks” better.

The problem which caused us to pull back and stick with arrow is that the return value is very primary to the functioning of the subscript, and colon reduced the visual weight of it, making it harder to pull out of code. The secondary issue is that the structure of a subscript definition is very strongly aligned with that of func decls, and changing this reduced that.

-Chris

···

On Jul 10, 2016, at 10:04 PM, Patrick Pijnappel via swift-evolution <swift-evolution@swift.org> wrote:

Good point. A subscript basically a parameterized property, not a function. I'm in favor.

On Mon, Jul 11, 2016 at 9:18 AM, James Froggatt via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Currently, the signature is:
subscript(_ example: Int) -> Element {
    get { … }
    set { … }
}

The alternative, using a colon, would be:
subscript(_ example: Int) : Element {
    get { … }
    set { … }
}

Sorry if that wasn't clear.

This would be to better reflect the property-like nature of access.

From James F

On 10 Jul 2016, at 23:57, Brent Royal-Gordon <brent@architechies.com <mailto:brent@architechies.com>> wrote:

>> On Jul 9, 2016, at 11:48 AM, James Froggatt via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>
>> Subscripts are a hybrid of properties and functions, since they have a parameter list, as well as getters and setters, so use of either symbol will be unusual in this case.
>>
>> However, I think a colon is more suitable, since it implies the possibility to set the value.
>
> Can you show us an example of the current syntax and your proposed replacement? I'm not sure what you actually mean by "use colons".
>
> --
> Brent Royal-Gordon
> Architechies
>
_______________________________________________
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
https://lists.swift.org/mailman/listinfo/swift-evolution

Thanks for letting me know this has been tried before, I'm actually in the process of drafting the proposal now.

I agree about the issue of the colon's visual weight, it's not ideal. On the other hand, I still find myself doing a mental double-take when reading ‘->’ in subscript declarations.

For subscripts, I think it's less a matter of ‘what existing category do we put them in?’, so much as it is about ‘what aspects do they borrow?’, and ‘how can we keep syntax consistent?’.

They borrow parameter lists, borrowing syntax from functions.
They borrow read-write access, which I feel should in turn borrow syntax from properties.

If we did want to align subscripts with function declarations, then we would be deciding on a new syntax for functions which allows get-set semantics, such as the following:

//subscript
subscript(_ position: Int) inout -> Element { get { … } set { … } }

//equivalent function
func item(at position: Int) inout -> Element { get { … } set { … } }

This would align them with functions better than the current syntax, by preserving the meaning of the ‘->’ to match functions.

But it's worth pointing out that even read-only subscripts can't throw - the similarity to functions is only superficial, and largely a result of the current syntax. These are very much properties with parameters.

I cannot argue with an internal trial, and I think that's a bit of a flaw of this mailing list system - many people making these proposals will not see these changes until they are out in the public. Certainly the proposal to remove argument labels could have benefitted from this kind of trial.

I'll continue the draft, to get some more feedback, but I'll be sure to point out the readability issue.

···

On 11 Jul 2016, at 18:45, Chris Lattner <clattner@apple.com> wrote:

FWIW, we actually tried this at one point with exactly this rationale, but pulled it back out. In short, subscript decls are half way between func decls and var decls. Reasonable arguments can be made to align with either of them, but arrow “looks” better.

The problem which caused us to pull back and stick with arrow is that the return value is very primary to the functioning of the subscript, and colon reduced the visual weight of it, making it harder to pull out of code. The secondary issue is that the structure of a subscript definition is very strongly aligned with that of func decls, and changing this reduced that.

-Chris

On Jul 10, 2016, at 10:04 PM, Patrick Pijnappel via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Good point. A subscript basically a parameterized property, not a function. I'm in favor.

On Mon, Jul 11, 2016 at 9:18 AM, James Froggatt via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Currently, the signature is:
subscript(_ example: Int) -> Element {
    get { … }
    set { … }
}

The alternative, using a colon, would be:
subscript(_ example: Int) : Element {
    get { … }
    set { … }
}

Sorry if that wasn't clear.

This would be to better reflect the property-like nature of access.

From James F

On 10 Jul 2016, at 23:57, Brent Royal-Gordon <brent@architechies.com <mailto:brent@architechies.com>> wrote:

>> On Jul 9, 2016, at 11:48 AM, James Froggatt via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>
>> Subscripts are a hybrid of properties and functions, since they have a parameter list, as well as getters and setters, so use of either symbol will be unusual in this case.
>>
>> However, I think a colon is more suitable, since it implies the possibility to set the value.
>
> Can you show us an example of the current syntax and your proposed replacement? I'm not sure what you actually mean by "use colons".
>
> --
> Brent Royal-Gordon
> Architechies
>
_______________________________________________
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

I've written up a draft proposal, suggestions or improvements are welcome, especially relating to the title.

__Change subscript declarations to use a colon__

--Introduction--

Currently, subscript declarations follow the following model:

subscript(externalName internalName: ParamType) -> ElementType {
    get { … }
    set { … }
}

The initial keyword ‘subscript’ is followed by a parameter list, followed by an arrow to the accessed type.

--Motivation--

The arrow, borrowed from function syntax, is very much out of place in this context, and so can act as a mental stumbling block.

Subscripts act like parameterised property accessors. This means, like a property, they can appear on the left hand side of an assignment, and values accessed through subscripts can be mutated in-place. The colon has precedent in declaring this kind of construct, so it makes sense to reuse it here.

--Proposed solution--

A simple replacement of ‘->’ with ‘:’ in the declaration syntax.

--Detailed design--

This would change the above example to look like the following:

subscript(externalName internalName: ParamType) : ElementType {
    get { … }
    set { … }
}

--Impact on existing code--

Existing code would have to update subscripts to use a colon. This can be automated in a conversion to Swift 3 syntax.

--Potential hazards--

Use of colons could have a negative effect on readability. This largely depends on coding style, which can match either of the following:

subscript(_ example: Type) : ElementType

subscript(_ example: Type): ElementType

This issue is most apparent in the latter example, which omits the leading space before the colon, as the colon blends into the closing bracket.

However, the real-world effect of this change is hard to predict, and subscript declarations are rare enough that the consequences of this change are very limited. In addition, the current ‘->‘ syntax can already act as a mental stumbling block.

--Alternatives Considered--

We could leave the syntax as it is, or use an alternative symbol, such as ‘:->’ or ‘<->’.

We could also leave open the possibility of expanding function syntax with ‘inout ->’.

Feels like an abuse of subscripting IMHO. I'm fine with parametrized properties but the subscript doesn't quite fit in this case.

···

Sent from my Apple Watch

On Jul 11, 2016, at 23:24, David Hart via swift-evolution <swift-evolution@swift.org> wrote:

How about a proposal for named subscripts?

button.image[for: .normal] = image

defined using:

subscript image(for: UIControlState): UIImage? {
  get { … }
  set { … }
}

On 12 Jul 2016, at 00:29, Tim Vermeulen via swift-evolution <swift-evolution@swift.org> wrote:

On 12 Jul 2016, at 00:20, Jacob Bandes-Storch <jtbandes@gmail.com> wrote:

When would you want to use this instead of something like `button[imageFor: .normal]` ?

All the time, basically. Primarily because IMO it doesn’t really make sense to make “image” part of the argument label for the control state - we just have to (using subscripts) because subscripts themselves can’t be named. I think most people would agree that

let image = button.image(for: .normal)

is more readable than

let image = button[imageFor: .normal]

and likewise, I would prefer

button.image(for: .normal) = image

over

button[imageFor: .normal] = image

On Mon, Jul 11, 2016 at 3:00 PM, Tim Vermeulen via swift-evolution <swift-evolution@swift.org> wrote:

Slightly related to this, I would really love to have non-subscript parameterized properties. It would allow us to write

button.image(for: .normal) = image

instead of

button.setImage(image, for: .normal)

The same can be achieved through subscripts, but it’s not always as nice. It would bring subscripts and computed properties closer together, which also seems to be the goal of your proposal. Perhaps the two ideas could be combined?

> Subscripts are a hybrid of properties and functions, since they have a parameter list, as well as getters and setters, so use of either symbol will be unusual in this case.
>
> However, I think a colon is more suitable, since it implies the possibility to set the value.
>
>
> In the future, if we add throwing getters/ setters:
>
> subscript(_ position: Int) ->Element {
> get {
> return …
> }
> throwing set {
> …
> }
> }
>
> Should this require ‘throws ->Element’? Using a colon also removes this potentially confusing case.
>
>
> Thoughts?
>
>
>

_______________________________________________
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

Then it kinda looks like your subscripting a property called `image`, doesn’t it?

···

On 12 Jul 2016, at 08:24, David Hart <david@hartbit.com> wrote:

How about a proposal for named subscripts?

button.image[for: .normal] = image

defined using:

subscript image(for: UIControlState): UIImage? {
  get { … }
  set { … }
}

On 12 Jul 2016, at 00:29, Tim Vermeulen via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On 12 Jul 2016, at 00:20, Jacob Bandes-Storch <jtbandes@gmail.com <mailto:jtbandes@gmail.com>> wrote:

When would you want to use this instead of something like `button[imageFor: .normal]` ?

All the time, basically. Primarily because IMO it doesn’t really make sense to make “image” part of the argument label for the control state - we just have to (using subscripts) because subscripts themselves can’t be named. I think most people would agree that

let image = button.image(for: .normal)

is more readable than

let image = button[imageFor: .normal]

and likewise, I would prefer

button.image(for: .normal) = image

over

button[imageFor: .normal] = image

On Mon, Jul 11, 2016 at 3:00 PM, Tim Vermeulen via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Slightly related to this, I would really love to have non-subscript parameterized properties. It would allow us to write

button.image(for: .normal) = image

instead of

button.setImage(image, for: .normal)

The same can be achieved through subscripts, but it’s not always as nice. It would bring subscripts and computed properties closer together, which also seems to be the goal of your proposal. Perhaps the two ideas could be combined?

> Subscripts are a hybrid of properties and functions, since they have a parameter list, as well as getters and setters, so use of either symbol will be unusual in this case.
>
> However, I think a colon is more suitable, since it implies the possibility to set the value.
>
>
> In the future, if we add throwing getters/ setters:
>
> subscript(_ position: Int) ->Element {
> get {
> return …
> }
> throwing set {
> …
> }
> }
>
> Should this require ‘throws ->Element’? Using a colon also removes this potentially confusing case.
>
>
> Thoughts?
>
>
>

_______________________________________________
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