Making `.self` After `Type` Optional


(Tanner Nelson) #1

Hello Swift Evolution members,

I would like to propose making `.self` After a Type optional when referencing Types in expressions.

Currently, to pass a Type to a function or method, it is sometimes required to add `.self` after the Type. This behavior is inconsistent as it is only required if the signature has more than one parameter.

Here is a demonstration of the current inconsistency.

func test<T: Any>(type: T.Type, two: String) {
    print(type)
}

func test<T: Any>(type: T.Type) {
    print(type)
}

test(Int.self)
test(Int)

test(Int.self, two: "")
test(Int, two: "") //Expected member name or constructor call after type name
      ^~~

This has been confirmed as a bug, and the report can be seen here <https://bugs.swift.org/browse/SR-899>.

After a Twitter conversation with Joe Groff on the Swift team (https://twitter.com/jckarter/status/707287663586324481) it is determined that this requirement is due to difficulty disambiguating generics `Foo<T>` vs infix less-than operations `Foo < T`.

I propose to allow Types to be used in expressions without needing to explicitly reference `.self`. The motivation for this is as follows:

- Cleaner API
- Consistent requirement is less confusing to developers
- Disambiguation challenges should not result in more verbose code unless absolutely necessary

Here are some preliminary ideas for how this could be implemented:

- Require spaces around less than expressions and no spaces around generics
- Require spaces around infix operators and no spaces around generics
- Remove less than overload for comparing a type
- (Your idea here)

A draft of an evolution document that provides more background can be viewed here <https://github.com/apple/swift-evolution/pull/197>. It has been preempted by a need for discussion in this mailing list.

I am looking forward to hearing your feedback on this proposal.

Thank you,
Tanner Nelson
http://github.com/tannernelson


(Brent Royal-Gordon) #2

I would like to propose making `.self` After a Type optional when referencing Types in expressions.

This has been confirmed as a bug, and the report can be seen here <https://bugs.swift.org/browse/SR-899>.

After a Twitter conversation with Joe Groff on the Swift team (https://twitter.com/jckarter/status/707287663586324481) it is determined that this requirement is due to difficulty disambiguating generics `Foo<T>` vs infix less-than operations `Foo < T`.

My understanding from previous Twitter discussions is that the primary reason for this feature is to keep you from writing `Foo` where you meant `Foo()`. That is, it's a deliberate design, meant to keep you from making mistakes. I suspect that you will have to overcome *that* impulse, not just any narrow parsing issue.

···

--
Brent Royal-Gordon
Architechies


(Dave Abrahams) #3

That is correct. Before 1.0, Swift used to work without ".self"; we
started requiring ".self" because one of the Swift designers
with experience in other languages that didn't require ".self" said that
it was a persistent source of confusion for users.

Personally, I've always disliked what ".self" did to my source code, but I
have no basis on which to argue with that other designer's experience.

···

on Wed Mar 09 2016, Brent Royal-Gordon <swift-evolution@swift.org> wrote:

I would like to propose making `.self` After a Type optional when referencing Types in expressions.

This has been confirmed as a bug, and the report can be seen here <https://bugs.swift.org/browse/SR-899>.

After a Twitter conversation with Joe Groff on the Swift team
(https://twitter.com/jckarter/status/707287663586324481) it is
determined that this requirement is due to difficulty disambiguating
generics `Foo<T>` vs infix less-than operations `Foo < T`.

My understanding from previous Twitter discussions is that the primary
reason for this feature is to keep you from writing `Foo` where you
meant `Foo()`. That is, it's a deliberate design, meant to keep you
from making mistakes. I suspect that you will have to overcome *that*
impulse, not just any narrow parsing issue.

--
-Dave


(Tanner Nelson) #4

That makes sense in the context of saying something like

  let foo = Foo.self

But I don't see any utility for method arguments since those will almost always be typed.

  func needsAnObject(object: Foo) {}

  needsAnObject(Foo)
                                  ^~~ cannot convert Foo.Type to Foo

···

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

I would like to propose making `.self` After a Type optional when referencing Types in expressions.

This has been confirmed as a bug, and the report can be seen here <https://bugs.swift.org/browse/SR-899>.

After a Twitter conversation with Joe Groff on the Swift team (https://twitter.com/jckarter/status/707287663586324481) it is determined that this requirement is due to difficulty disambiguating generics `Foo<T>` vs infix less-than operations `Foo < T`.

My understanding from previous Twitter discussions is that the primary reason for this feature is to keep you from writing `Foo` where you meant `Foo()`. That is, it's a deliberate design, meant to keep you from making mistakes. I suspect that you will have to overcome *that* impulse, not just any narrow parsing issue.

--
Brent Royal-Gordon
Architechies

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


(Haravikk) #5

While I know some people’s preference is for spacing to be left to linters and other tools, I do think that requiring space around operators is a good requirement to make; it should make it easier for the compiler, and easier for readability, plus it actually fits with Swift’s goal of avoiding mistakes by making it harder to mistakenly use negation vs subtract and other weird cases (like this particular one).

I’d say that all operators taking two arguments should have whitespace on either side, while prefix and postfix operators shouldn’t be allowed to have trailing and leading space respectively (the latter may already be the case, I can’t check just now).

That said, I’d say that removing comparison operators from types make sense too, as I can’t imagine when you’d need to do this?

So put in the “little bit of everything” camp :wink:

···

On 9 Mar 2016, at 19:23, Tanner Nelson via swift-evolution <swift-evolution@swift.org> wrote:

- Require spaces around infix operators and no spaces around generics


(Sean Heber) #6

Bumping this - did anything ever become of this? It seemed like there was general agreement to do something about the “.self” requirement when referencing types. I would personally like to see it go away.

l8r
Sean

···

On Mar 9, 2016, at 1:23 PM, Tanner Nelson via swift-evolution <swift-evolution@swift.org> wrote:

Hello Swift Evolution members,

I would like to propose making `.self` After a Type optional when referencing Types in expressions.

Currently, to pass a Type to a function or method, it is sometimes required to add `.self` after the Type. This behavior is inconsistent as it is only required if the signature has more than one parameter.

Here is a demonstration of the current inconsistency.

func test<T: Any>(type: T.Type, two: String) {
   print(type)
}

func test<T: Any>(type: T.Type) {
   print(type)
}

test(Int.self)
test(Int)

test(Int.self, two: "")
test(Int, two: "") //Expected member name or constructor call after type name
     ^~~

This has been confirmed as a bug, and the report can be seen here <https://bugs.swift.org/browse/SR-899>.

After a Twitter conversation with Joe Groff on the Swift team (https://twitter.com/jckarter/status/707287663586324481) it is determined that this requirement is due to difficulty disambiguating generics `Foo<T>` vs infix less-than operations `Foo < T`.

I propose to allow Types to be used in expressions without needing to explicitly reference `.self`. The motivation for this is as follows:

- Cleaner API
- Consistent requirement is less confusing to developers
- Disambiguation challenges should not result in more verbose code unless absolutely necessary

Here are some preliminary ideas for how this could be implemented:

- Require spaces around less than expressions and no spaces around generics
- Require spaces around infix operators and no spaces around generics
- Remove less than overload for comparing a type
- (Your idea here)

A draft of an evolution document that provides more background can be viewed here <https://github.com/apple/swift-evolution/pull/197>. It has been preempted by a need for discussion in this mailing list.

I am looking forward to hearing your feedback on this proposal.

Thank you,
Tanner Nelson
http://github.com/tannernelson

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


(Joe Groff) #7

To keep progress going on this, I collected my thoughts from March's discussion into a draft proposal:

https://github.com/apple/swift-evolution/pull/299

-Joe

···

On Mar 9, 2016, at 11:23 AM, Tanner Nelson via swift-evolution <swift-evolution@swift.org> wrote:

Hello Swift Evolution members,

I would like to propose making `.self` After a Type optional when referencing Types in expressions.

Currently, to pass a Type to a function or method, it is sometimes required to add `.self` after the Type. This behavior is inconsistent as it is only required if the signature has more than one parameter.

Here is a demonstration of the current inconsistency.

func test<T: Any>(type: T.Type, two: String) {
   print(type)
}

func test<T: Any>(type: T.Type) {
   print(type)
}

test(Int.self)
test(Int)

test(Int.self, two: "")
test(Int, two: "") //Expected member name or constructor call after type name
     ^~~

This has been confirmed as a bug, and the report can be seen here <https://bugs.swift.org/browse/SR-899>.

After a Twitter conversation with Joe Groff on the Swift team (https://twitter.com/jckarter/status/707287663586324481) it is determined that this requirement is due to difficulty disambiguating generics `Foo<T>` vs infix less-than operations `Foo < T`.

I propose to allow Types to be used in expressions without needing to explicitly reference `.self`. The motivation for this is as follows:

- Cleaner API
- Consistent requirement is less confusing to developers
- Disambiguation challenges should not result in more verbose code unless absolutely necessary

Here are some preliminary ideas for how this could be implemented:

- Require spaces around less than expressions and no spaces around generics
- Require spaces around infix operators and no spaces around generics
- Remove less than overload for comparing a type
- (Your idea here)

A draft of an evolution document that provides more background can be viewed here <https://github.com/apple/swift-evolution/pull/197>. It has been preempted by a need for discussion in this mailing list.

I am looking forward to hearing your feedback on this proposal.

Thank you,
Tanner Nelson
http://github.com/tannernelson

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


(Joe Groff) #8

As the designer in question, I've come around to this as well; our type system is sufficiently stronger than that other language that I think the consequences of accidentally typing `let x = Int` when you meant `let x = Int()` are far easier to understand. However, `.self` is also a bit of load-bearing duct-tape that currently supports some other parsing aspects of Swift's syntax. We have a bunch of type sugar syntax that's overloaded with expression syntax, such as Int?, [Int], [String: Int], and (String, Int); we currently handle this by special-casing the sugar forms when they appear as the LHS of a member lookup or function call. We could address that problem by treating it more like an overload resolution problem, and say that applying `[]`, `[:]`, `?`, or `(,)` to type references always favors building a type reference over forming an array/dictionary/optional/tuple. There's also the lower-level parsing problem with generic parameter brackets that Tanner mentioned in his leading email. We stole the same trick that C# uses to disambiguate `Foo<T, U>(x)` from `(Foo < T), (U > (x))` without relying on name lookup; we assume that a type reference in an expression is always the root of a member lookup or constructor call, and that 'x > (y)' is sufficiently unlikely given the low relative precedence of >, that we can look ahead after we see a '<' to find a '>.' or '>(' token pair and favor the parse as a generic parameter list in those cases. If we're going to break the invariant that type references in expressions are always followed by a member lookup or constructor call, we'll need an alternative disambiguation scheme.

-Joe

···

On Mar 9, 2016, at 2:28 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:

on Wed Mar 09 2016, Brent Royal-Gordon <swift-evolution@swift.org> wrote:

I would like to propose making `.self` After a Type optional when referencing Types in expressions.

This has been confirmed as a bug, and the report can be seen here <https://bugs.swift.org/browse/SR-899>.

After a Twitter conversation with Joe Groff on the Swift team
(https://twitter.com/jckarter/status/707287663586324481) it is
determined that this requirement is due to difficulty disambiguating
generics `Foo<T>` vs infix less-than operations `Foo < T`.

My understanding from previous Twitter discussions is that the primary
reason for this feature is to keep you from writing `Foo` where you
meant `Foo()`. That is, it's a deliberate design, meant to keep you
from making mistakes. I suspect that you will have to overcome *that*
impulse, not just any narrow parsing issue.

That is correct. Before 1.0, Swift used to work without ".self"; we
started requiring ".self" because one of the Swift designers
with experience in other languages that didn't require ".self" said that
it was a persistent source of confusion for users.

Personally, I've always disliked what ".self" did to my source code, but I
have no basis on which to argue with that other designer's experience.


(Joe Groff) #9

We really want this to be a parse-time disambiguation so that the grammar isn't dependent on name lookup like C is. Banning the '<' operator on types doesn't help because at parse time we don't even know whether we have a type reference or not.

-Joe

···

On Mar 10, 2016, at 3:00 AM, Haravikk via swift-evolution <swift-evolution@swift.org> wrote:

On 9 Mar 2016, at 19:23, Tanner Nelson via swift-evolution <swift-evolution@swift.org> wrote:

- Require spaces around infix operators and no spaces around generics

While I know some people’s preference is for spacing to be left to linters and other tools, I do think that requiring space around operators is a good requirement to make; it should make it easier for the compiler, and easier for readability, plus it actually fits with Swift’s goal of avoiding mistakes by making it harder to mistakenly use negation vs subtract and other weird cases (like this particular one).

I’d say that all operators taking two arguments should have whitespace on either side, while prefix and postfix operators shouldn’t be allowed to have trailing and leading space respectively (the latter may already be the case, I can’t check just now).

That said, I’d say that removing comparison operators from types make sense too, as I can’t imagine when you’d need to do this?


(Tanner Nelson) #10

I'm wondering if this mailing list is the best place to discuss the implementation details. The proposal PR was closed because the motivation was not clear. But it seems like we have sufficient motivation from the responses to this thread so far.

I would much rather be pasting code snippets in GitHub comments with the nice syntax formatting.

···

On Mar 10, 2016, at 11:14 AM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

On Mar 10, 2016, at 3:00 AM, Haravikk via swift-evolution <swift-evolution@swift.org> wrote:

On 9 Mar 2016, at 19:23, Tanner Nelson via swift-evolution <swift-evolution@swift.org> wrote:

- Require spaces around infix operators and no spaces around generics

While I know some people’s preference is for spacing to be left to linters and other tools, I do think that requiring space around operators is a good requirement to make; it should make it easier for the compiler, and easier for readability, plus it actually fits with Swift’s goal of avoiding mistakes by making it harder to mistakenly use negation vs subtract and other weird cases (like this particular one).

I’d say that all operators taking two arguments should have whitespace on either side, while prefix and postfix operators shouldn’t be allowed to have trailing and leading space respectively (the latter may already be the case, I can’t check just now).

That said, I’d say that removing comparison operators from types make sense too, as I can’t imagine when you’d need to do this?

We really want this to be a parse-time disambiguation so that the grammar isn't dependent on name lookup like C is. Banning the '<' operator on types doesn't help because at parse time we don't even know whether we have a type reference or not.

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


(David Sweeris) #11

+1

- Require spaces around infix operators and no spaces around generics

While I know some people’s preference is for spacing to be left to linters and other tools, I do think that requiring space around operators is a good requirement to make; it should make it easier for the compiler, and easier for readability, plus it actually fits with Swift’s goal of avoiding mistakes by making it harder to mistakenly use negation vs subtract and other weird cases (like this particular one).

I’d say that all operators taking two arguments should have whitespace on either side, while prefix and postfix operators shouldn’t be allowed to have trailing and leading space respectively (the latter may already be the case, I can’t check just now).

-1, for the reason Joe Groff gave, plus I don’t like the idea of these kinds of special cases (or special cases in general, come to think of it).

That said, I’d say that removing comparison operators from types make sense too, as I can’t imagine when you’d need to do this?

- Dave Sweeris

···

On Mar 10, 2016, at 5:00 AM, Haravikk via swift-evolution <swift-evolution@swift.org> wrote:

On 9 Mar 2016, at 19:23, Tanner Nelson via swift-evolution <swift-evolution@swift.org> wrote:


(Matthew Johnson) #12

Definitely +1 to removing the .self requirement.

···

Sent from my iPad

On May 5, 2016, at 11:34 PM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

To keep progress going on this, I collected my thoughts from March's discussion into a draft proposal:

https://github.com/apple/swift-evolution/pull/299

-Joe

On Mar 9, 2016, at 11:23 AM, Tanner Nelson via swift-evolution <swift-evolution@swift.org> wrote:

Hello Swift Evolution members,

I would like to propose making `.self` After a Type optional when referencing Types in expressions.

Currently, to pass a Type to a function or method, it is sometimes required to add `.self` after the Type. This behavior is inconsistent as it is only required if the signature has more than one parameter.

Here is a demonstration of the current inconsistency.

func test<T: Any>(type: T.Type, two: String) {
  print(type)
}

func test<T: Any>(type: T.Type) {
  print(type)
}

test(Int.self)
test(Int)

test(Int.self, two: "")
test(Int, two: "") //Expected member name or constructor call after type name
    ^~~

This has been confirmed as a bug, and the report can be seen here <https://bugs.swift.org/browse/SR-899>.

After a Twitter conversation with Joe Groff on the Swift team (https://twitter.com/jckarter/status/707287663586324481) it is determined that this requirement is due to difficulty disambiguating generics `Foo<T>` vs infix less-than operations `Foo < T`.

I propose to allow Types to be used in expressions without needing to explicitly reference `.self`. The motivation for this is as follows:

- Cleaner API
- Consistent requirement is less confusing to developers
- Disambiguation challenges should not result in more verbose code unless absolutely necessary

Here are some preliminary ideas for how this could be implemented:

- Require spaces around less than expressions and no spaces around generics
- Require spaces around infix operators and no spaces around generics
- Remove less than overload for comparing a type
- (Your idea here)

A draft of an evolution document that provides more background can be viewed here <https://github.com/apple/swift-evolution/pull/197>. It has been preempted by a need for discussion in this mailing list.

I am looking forward to hearing your feedback on this proposal.

Thank you,
Tanner Nelson
http://github.com/tannernelson

_______________________________________________
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


(David Hart) #13

I understand why the alternative of changing the generic type parameter list symbols was rejected, to be consistent with other C based languages, but I don't understand why the following was rejected:

making the UppercaseTypes, lowercaseValues convention a syntactic requirement, as is done in ML and Haskell.
I see that as a good viable alternative.

···

On 06 May 2016, at 06:34, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

To keep progress going on this, I collected my thoughts from March's discussion into a draft proposal:

https://github.com/apple/swift-evolution/pull/299

-Joe

On Mar 9, 2016, at 11:23 AM, Tanner Nelson via swift-evolution <swift-evolution@swift.org> wrote:

Hello Swift Evolution members,

I would like to propose making `.self` After a Type optional when referencing Types in expressions.

Currently, to pass a Type to a function or method, it is sometimes required to add `.self` after the Type. This behavior is inconsistent as it is only required if the signature has more than one parameter.

Here is a demonstration of the current inconsistency.

func test<T: Any>(type: T.Type, two: String) {
  print(type)
}

func test<T: Any>(type: T.Type) {
  print(type)
}

test(Int.self)
test(Int)

test(Int.self, two: "")
test(Int, two: "") //Expected member name or constructor call after type name
    ^~~

This has been confirmed as a bug, and the report can be seen here <https://bugs.swift.org/browse/SR-899>.

After a Twitter conversation with Joe Groff on the Swift team (https://twitter.com/jckarter/status/707287663586324481) it is determined that this requirement is due to difficulty disambiguating generics `Foo<T>` vs infix less-than operations `Foo < T`.

I propose to allow Types to be used in expressions without needing to explicitly reference `.self`. The motivation for this is as follows:

- Cleaner API
- Consistent requirement is less confusing to developers
- Disambiguation challenges should not result in more verbose code unless absolutely necessary

Here are some preliminary ideas for how this could be implemented:

- Require spaces around less than expressions and no spaces around generics
- Require spaces around infix operators and no spaces around generics
- Remove less than overload for comparing a type
- (Your idea here)

A draft of an evolution document that provides more background can be viewed here <https://github.com/apple/swift-evolution/pull/197>. It has been preempted by a need for discussion in this mailing list.

I am looking forward to hearing your feedback on this proposal.

Thank you,
Tanner Nelson
http://github.com/tannernelson

_______________________________________________
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


(Tanner) #14

"our type system is sufficiently stronger than that other language..."

I was just writing a response that said exactly this. It's really impossible in Swift to be unknowingly sending the wrong types around.

If the agreement seems to be leaning toward figuring out a way to remove `.self`, what would the next steps be to start concretely seeing which implementations might work / be realistic?

···

On Mar 9, 2016, at 5:57 PM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

On Mar 9, 2016, at 2:28 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:

on Wed Mar 09 2016, Brent Royal-Gordon <swift-evolution@swift.org> wrote:

I would like to propose making `.self` After a Type optional when referencing Types in expressions.

This has been confirmed as a bug, and the report can be seen here <https://bugs.swift.org/browse/SR-899>.

After a Twitter conversation with Joe Groff on the Swift team
(https://twitter.com/jckarter/status/707287663586324481) it is
determined that this requirement is due to difficulty disambiguating
generics `Foo<T>` vs infix less-than operations `Foo < T`.

My understanding from previous Twitter discussions is that the primary
reason for this feature is to keep you from writing `Foo` where you
meant `Foo()`. That is, it's a deliberate design, meant to keep you
from making mistakes. I suspect that you will have to overcome *that*
impulse, not just any narrow parsing issue.

That is correct. Before 1.0, Swift used to work without ".self"; we
started requiring ".self" because one of the Swift designers
with experience in other languages that didn't require ".self" said that
it was a persistent source of confusion for users.

Personally, I've always disliked what ".self" did to my source code, but I
have no basis on which to argue with that other designer's experience.

As the designer in question, I've come around to this as well; our type system is sufficiently stronger than that other language that I think the consequences of accidentally typing `let x = Int` when you meant `let x = Int()` are far easier to understand. However, `.self` is also a bit of load-bearing duct-tape that currently supports some other parsing aspects of Swift's syntax. We have a bunch of type sugar syntax that's overloaded with expression syntax, such as Int?, [Int], [String: Int], and (String, Int); we currently handle this by special-casing the sugar forms when they appear as the LHS of a member lookup or function call. We could address that problem by treating it more like an overload resolution problem, and say that applying `[]`, `[:]`, `?`, or `(,)` to type references always favors building a type reference over forming an array/dictionary/optional/tuple. There's also the lower-level parsing problem with generic parameter brackets that Tanner mentioned in his leading email. We stole the same trick that C# uses to disambiguate `Foo<T, U>(x)` from `(Foo < T), (U > (x))` without relying on name lookup; we assume that a type reference in an expression is always the root of a member lookup or constructor call, and that 'x > (y)' is sufficiently unlikely given the low relative precedence of >, that we can look ahead after we see a '<' to find a '>.' or '>(' token pair and favor the parse as a generic parameter list in those cases. If we're going to break the invariant that type references in expressions are always followed by a member lookup or constructor call, we'll need an alternative disambiguation scheme.

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


(Joe Groff) #15

I'm wondering if this mailing list is the best place to discuss the implementation details. The proposal PR was closed because the motivation was not clear. But it seems like we have sufficient motivation from the responses to this thread so far.

I would much rather be pasting code snippets in GitHub comments with the nice syntax formatting.

If you want to discuss Swift language design, this is the place.

-Joe

···

On Mar 10, 2016, at 9:15 AM, Tanner Nelson <tannernelson@gmail.com> wrote:

On Mar 10, 2016, at 11:14 AM, Joe Groff via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Mar 10, 2016, at 3:00 AM, Haravikk via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On 9 Mar 2016, at 19:23, Tanner Nelson via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

- Require spaces around infix operators and no spaces around generics

While I know some people’s preference is for spacing to be left to linters and other tools, I do think that requiring space around operators is a good requirement to make; it should make it easier for the compiler, and easier for readability, plus it actually fits with Swift’s goal of avoiding mistakes by making it harder to mistakenly use negation vs subtract and other weird cases (like this particular one).

I’d say that all operators taking two arguments should have whitespace on either side, while prefix and postfix operators shouldn’t be allowed to have trailing and leading space respectively (the latter may already be the case, I can’t check just now).

That said, I’d say that removing comparison operators from types make sense too, as I can’t imagine when you’d need to do this?

We really want this to be a parse-time disambiguation so that the grammar isn't dependent on name lookup like C is. Banning the '<' operator on types doesn't help because at parse time we don't even know whether we have a type reference or not.

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


(Austin Zheng) #16

+1 to David's point. Given that Swift's naming conventions already diverge from C's (and we have things like 'Self' vs 'self'), it seems like enforcing this relatively uncontroversial best practice would be an overall win.

Austin

···

On May 6, 2016, at 12:04 AM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:

I understand why the alternative of changing the generic type parameter list symbols was rejected, to be consistent with other C based languages, but I don't understand why the following was rejected:

making the UppercaseTypes, lowercaseValues convention a syntactic requirement, as is done in ML and Haskell.
I see that as a good viable alternative.

On 06 May 2016, at 06:34, Joe Groff via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

To keep progress going on this, I collected my thoughts from March's discussion into a draft proposal:

https://github.com/apple/swift-evolution/pull/299

-Joe

On Mar 9, 2016, at 11:23 AM, Tanner Nelson via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hello Swift Evolution members,

I would like to propose making `.self` After a Type optional when referencing Types in expressions.

Currently, to pass a Type to a function or method, it is sometimes required to add `.self` after the Type. This behavior is inconsistent as it is only required if the signature has more than one parameter.

Here is a demonstration of the current inconsistency.

func test<T: Any>(type: T.Type, two: String) {
  print(type)
}

func test<T: Any>(type: T.Type) {
  print(type)
}

test(Int.self)
test(Int)

test(Int.self, two: "")
test(Int, two: "") //Expected member name or constructor call after type name
    ^~~

This has been confirmed as a bug, and the report can be seen here <https://bugs.swift.org/browse/SR-899>.

After a Twitter conversation with Joe Groff on the Swift team (https://twitter.com/jckarter/status/707287663586324481) it is determined that this requirement is due to difficulty disambiguating generics `Foo<T>` vs infix less-than operations `Foo < T`.

I propose to allow Types to be used in expressions without needing to explicitly reference `.self`. The motivation for this is as follows:

- Cleaner API
- Consistent requirement is less confusing to developers
- Disambiguation challenges should not result in more verbose code unless absolutely necessary

Here are some preliminary ideas for how this could be implemented:

- Require spaces around less than expressions and no spaces around generics
- Require spaces around infix operators and no spaces around generics
- Remove less than overload for comparing a type
- (Your idea here)

A draft of an evolution document that provides more background can be viewed here <https://github.com/apple/swift-evolution/pull/197>. It has been preempted by a need for discussion in this mailing list.

I am looking forward to hearing your feedback on this proposal.

Thank you,
Tanner Nelson
http://github.com/tannernelson

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

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

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


(Joe Groff) #17

The challenges with making that work include:

- Deciding what to do with imported C APIs. Core Foundation uses CFUppercaseEverything, and POSIX prefers snake_case_t and snake_case_functions. In the early days, we were shy about transforming imported APIs at all, but we've obviously gotten more comfortable with it as Swift's established itself and its own conventions have emerged.
- Providing an alternative for non-Latin scripts that don't differentiate case, such as Arabic and Chinese (and, somewhat related, deciding whether non-letter identifier characters like emoji are "value" or "type" characters).

-Joe

···

On May 6, 2016, at 12:04 AM, David Hart <david@hartbit.com> wrote:

I understand why the alternative of changing the generic type parameter list symbols was rejected, to be consistent with other C based languages, but I don't understand why the following was rejected:

  • making the UppercaseTypes, lowercaseValues convention a syntactic requirement, as is done in ML and Haskell.
I see that as a good viable alternative.


(Pyry Jahkola) #18

I understand why the alternative of changing the generic type parameter list symbols was rejected, to be consistent with other C based languages, but I don't understand why the following was rejected:

making the UppercaseTypes, lowercaseValues convention a syntactic requirement, as is done in ML and Haskell.
I see that as a good viable alternative.

+1, enforcing the initial character case of type and value identifiers would clear up the language IMO.

It would also mean we'd need to bridge all C APIs in correct case.

Also, in general +1 to getting rid of `.self`.

— Pyry


(David Hart) #19

I strongly agree for the removal of .self. I remember it being a great source of confusion when I first learned Swift.

···

On 10 Mar 2016, at 00:03, Tanner Nelson via swift-evolution <swift-evolution@swift.org> wrote:

"our type system is sufficiently stronger than that other language..."

I was just writing a response that said exactly this. It's really impossible in Swift to be unknowingly sending the wrong types around.

If the agreement seems to be leaning toward figuring out a way to remove `.self`, what would the next steps be to start concretely seeing which implementations might work / be realistic?

On Mar 9, 2016, at 5:57 PM, Joe Groff via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Mar 9, 2016, at 2:28 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

on Wed Mar 09 2016, Brent Royal-Gordon <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I would like to propose making `.self` After a Type optional when referencing Types in expressions.

This has been confirmed as a bug, and the report can be seen here <https://bugs.swift.org/browse/SR-899>.

After a Twitter conversation with Joe Groff on the Swift team
(https://twitter.com/jckarter/status/707287663586324481) it is
determined that this requirement is due to difficulty disambiguating
generics `Foo<T>` vs infix less-than operations `Foo < T`.

My understanding from previous Twitter discussions is that the primary
reason for this feature is to keep you from writing `Foo` where you
meant `Foo()`. That is, it's a deliberate design, meant to keep you
from making mistakes. I suspect that you will have to overcome *that*
impulse, not just any narrow parsing issue.

That is correct. Before 1.0, Swift used to work without ".self"; we
started requiring ".self" because one of the Swift designers
with experience in other languages that didn't require ".self" said that
it was a persistent source of confusion for users.

Personally, I've always disliked what ".self" did to my source code, but I
have no basis on which to argue with that other designer's experience.

As the designer in question, I've come around to this as well; our type system is sufficiently stronger than that other language that I think the consequences of accidentally typing `let x = Int` when you meant `let x = Int()` are far easier to understand. However, `.self` is also a bit of load-bearing duct-tape that currently supports some other parsing aspects of Swift's syntax. We have a bunch of type sugar syntax that's overloaded with expression syntax, such as Int?, [Int], [String: Int], and (String, Int); we currently handle this by special-casing the sugar forms when they appear as the LHS of a member lookup or function call. We could address that problem by treating it more like an overload resolution problem, and say that applying `[]`, `[:]`, `?`, or `(,)` to type references always favors building a type reference over forming an array/dictionary/optional/tuple. There's also the lower-level parsing problem with generic parameter brackets that Tanner mentioned in his leading email. We stole the same trick that C# uses to disambiguate `Foo<T, U>(x)` from `(Foo < T), (U > (x))` without relying on name lookup; we assume that a type reference in an expression is always the root of a member lookup or constructor call, and that 'x > (y)' is sufficiently unlikely given the low relative precedence of >, that we can look ahead after we see a '<' to find a '>.' or '>(' token pair and favor the parse as a generic parameter list in those cases. If we're going to break the invariant that type references in expressions are always followed by a member lookup or constructor call, we'll need an alternative disambiguation scheme.

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


(Joe Groff) #20

I see two problems to solve:

A) Decide a grammar rule to distinguish the operator '<' from the generic parameter bracket, and
B) Decide a semantic rule to distinguish type "operators" like '[T]', 'T?', etc. from value operations.

For (A), we should look at the new places a generic type might appear in expressions:

- By itself:

let x = Foo< T >
bar() // following statement

let y = Foo< T, U >
bar() // following statement

This doesn't strike me as a huge problem to parse as a type reference, since 'a < b > c' is unlikely as an expression, and we don't have commas in the top level of the grammar, so 'a < b, c > d' is impossible as a top-level expression. Extending the lookahead rule to include `>;` or `> *token on next line*` as disambiguators is probably OK.

- As a function parameter, or array or dictionary element:

sizeof(Foo<T>)
load(Foo<T>, atOffset: 8)
let types = [Foo<T>, Bar<U>]
let factories = [Foo<T>: makeFoo, Bar<U>: makeBar]

This is probably the most common use case for type references, and the easiest to support, since the parameters are always followed by a token that can't start an expression by itself. We could extend the current lookahead rule to ensure it includes `>)`, `>,` and `>:`.

- As the parameter to an operator:

++Foo<T> // prefix
Foo<T>++ // postfix
Foo<T>+Bar<U> // infix
Foo<T> + Bar<U>
let foo = Bar<U>

This one's a bit interesting since `>+` or `>++` could be operators themselves. Applying operators to types might not be a compelling enough reason to block the other changes, though.

For (B), as I mentioned before, it makes the choice between [T] becoming 'Array<T>' or becoming an array containing 'T' a bit of an overload resolution problem. In most cases we can probably favor the type sugar, either by argument type context or by syntactically recognizing `T` as a static type reference and favoring the type sugar interpretation over the array literal implementation. Doug or Joe Pamer probably have opinions here.

-Joe

···

On Mar 9, 2016, at 3:03 PM, Tanner Nelson <me@tanner.xyz> wrote:

"our type system is sufficiently stronger than that other language..."

I was just writing a response that said exactly this. It's really impossible in Swift to be unknowingly sending the wrong types around.

If the agreement seems to be leaning toward figuring out a way to remove `.self`, what would the next steps be to start concretely seeing which implementations might work / be realistic?