[pitch] Eliminate the "T1 -> T2" syntax, require "(T1) -> T2"

+1, but this proposal need further work.
Specification of the new function grammar is needed.

Currently, it looks like:

function-type → type
<Types — The Swift Programming Language (Swift 5.7);
­throws­opt­->­type
<Types — The Swift Programming Language (Swift 5.7);

It is already false, because some attributes can only be used in function
types.

I suggest to rewrite it to something like:

*function-type* → ( *function-parameter-types*opt ) -> *type*

*function-type* → ( *function-parameter-types*opt ) throws -> *type*

*function-type* → ( *function-parameter-types*opt ) rethrows -> *type*

*function-parameter-types* → *function-parameter-type*

*function-parameter-types* → *function-parameter-type* ,
*function-parameter-types*

*function-parameter-type* → *function-parameter-attributes* *type*
It will also eliminate situation when you can pass () argument to a () → T
function.
Function types Void->T will need to be migrated.

- Anton

IMO +1 for Антон's suggestion, but

"It will also eliminate situation when you can pass () argument to a () → T
function."

What do you think about the result "type":

typealias f1 = () -> Void
typealias f2 = () -> ((Void))
typealias f3 = () -> (())
typealias f4 = () -> ((((((()))))))

They are all equal definition now. In your opinion, should we change this also in some way?

···

On 22.04.2016 11:12, Антон Жилин via swift-evolution wrote:

+1, but this proposal need further work.
Specification of the new function grammar is needed.

Currently, it looks like:

function-type → type
<The Swift Programming Language: Redirect
­|->­|type
<The Swift Programming Language: Redirect;

It is already false, because some attributes can only be used in function
types.

I suggest to rewrite it to something like:

/function-type/ → |(| /function-parameter-types/_opt |)| |->| /type/

/function-type/ → |(| /function-parameter-types/_opt |)| |throws| |->| /type/

/function-type/ → |(| /function-parameter-types/_opt
>)| |rethrows| |->| /type/

/function-parameter-types/ → /function-parameter-type/

/function-parameter-types/ → /function-parameter-type/ |,| /function-parameter-types/

/function-parameter-type/ → /function-parameter-attributes/ /type/

It will also eliminate situation when you can pass () argument to a () → T
function.
Function types Void->T will need to be migrated.

- Anton

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

Vladimir, I agree with Chris Lattner that function parameters are different
from function return value in Swift.

Firstly, syntax of function call allows for easy forwarding of values,
which came from different places, as parameters to a single function:
f(g(foo, 1), h(bar(buz)))

On the other hand, to play with multiple return values as freely, you need
to perform pattern matching, which finishes current expression.

Secondly, there is no special sugar for tuples in return values, and
function grammar does not need to know about it.

Thirdly, there are no special attributes for elements of tuple in function
return type (second implies this).

Now, to typealias f4 = () -> ((((((()))))))
I think it's OK, but we can remove Void and reduce the number of possible
combinations.

The fact that () and (()) are equal types is a general limitation of Swift
type system: there are no single-element tuples.
But it is so for a reason: parentheses in expressions cannot be overloaded
to construct single-element tuples.

- Anton

···

2016-04-22 11:12 GMT+03:00 Антон Жилин <antonyzhilin@gmail.com>:

+1, but this proposal need further work.
Specification of the new function grammar is needed.

Currently, it looks like:

function-type → type
<The Swift Programming Language: Redirect;
­throws­opt­->­type
<The Swift Programming Language: Redirect;

It is already false, because some attributes can only be used in function
types.

I suggest to rewrite it to something like:

*function-type* → ( *function-parameter-types*opt ) -> *type*

*function-type* → ( *function-parameter-types*opt ) throws -> *type*

*function-type* → ( *function-parameter-types*opt ) rethrows -> *type*

*function-parameter-types* → *function-parameter-type*

*function-parameter-types* → *function-parameter-type* ,
*function-parameter-types*

*function-parameter-type* → *function-parameter-attributes* *type*
It will also eliminate situation when you can pass () argument to a () → T
function.
Function types Void->T will need to be migrated.

- Anton

Vladimir, I agree with Chris Lattner that function parameters are different
from function return value in Swift.

Firstly, syntax of function call allows for easy forwarding of values,
which came from different places, as parameters to a single function:
f(g(foo, 1), h(bar(buz)))

On the other hand, to play with multiple return values as freely, you need
to perform pattern matching, which finishes current expression.

Secondly, there is no special sugar for tuples in return values, and
function grammar does not need to know about it.

Thirdly, there are no special attributes for elements of tuple in function
return type (second implies this).

I see your points regarding the function parameters. And I'm ready to totally agree with you.

Now, to typealias f4 = () -> ((((((()))))))
I think it's OK, but we can remove Void and reduce the number of possible
combinations.

Yes, my question was actually about the result type syntax like (Void) (()) (((()))) etc, if you feel this is OK to have this in Swift.
I think the possibility to have (((()))) is weird, not useful, never can be used and just shouldn't exist in the language. Why not prevent this just by .. compiler/syntax checker/parser..
Probably I'm missing somehting.. ?

About the "Void".. I'm +1 on this idea, but asking myself if we can freely remove 'Void' from our language at all without any problem? Can't find the answer. It seems like we can, IMO using the syntax like () -> () is OK, clear and explicit, especially in "functional" word.

···

On 22.04.2016 20:17, Антон Жилин wrote:

The fact that () and (()) are equal types is a general limitation of Swift
type system: there are no single-element tuples.
But it is so for a reason: parentheses in expressions cannot be overloaded
to construct single-element tuples.

- Anton

2016-04-22 11:12 GMT+03:00 Антон Жилин <antonyzhilin@gmail.com
<mailto:antonyzhilin@gmail.com>>:

    +1, but this proposal need further work.
    Specification of the new function grammar is needed.

    Currently, it looks like:

    function-type → type
    <The Swift Programming Language: Redirect
    ­|->­|type
    <The Swift Programming Language: Redirect;

    It is already false, because some attributes can only be used in
    function types.

    I suggest to rewrite it to something like:

    /function-type/ → |(| /function-parameter-types/_opt |)| |->| /type/

    /function-type/ → |(| /function-parameter-types/_opt
     >)| |throws| |->| /type/

    /function-type/ → |(| /function-parameter-types/_opt
     >)| |rethrows| |->| /type/

    /function-parameter-types/ → /function-parameter-type/

    /function-parameter-types/ → /function-parameter-type/ |,| /function-parameter-types/

    /function-parameter-type/ → /function-parameter-attributes/ /type/

    It will also eliminate situation when you can pass () argument to a ()
    → T function.
    Function types Void->T will need to be migrated.

    - Anton

We can disallow putting types in parentheses in single-element tuple
meaning.
For example, (Int) -> (Double) will be illegal because of (Double).
(Int) -> (Double) -> Bool will be legal, because parentheses mean function
type here.
(Int) -> () will be legal, because () means Void here.
This can be theme of a separate proposal.

- Anton

···

On 22.04.16, Vladimir.S wrote:

What I really don't like is that we can have all this:
func f1() -> (Void) {..}
func f2(Void) -> ((Void)) {..}
func f3() -> (((()))) {..}
func f4(((Void))) -> (Void) {..}
func f5() -> ((Void)) {..}
func f6((())) -> (((()))) {..}
and all is equivalent for
func f() -> () {..}

I like having Void as a typealias of (), and would prefer to retain it in the language if possible.

···

On Apr 22, 2016, at 12:08 PM, Vladimir.S via swift-evolution <swift-evolution@swift.org> wrote:
About the "Void".. I'm +1 on this idea, but asking myself if we can freely remove 'Void' from our language at all without any problem? Can't find the answer. It seems like we can, IMO using the syntax like () -> () is OK, clear and explicit, especially in "functional" word.

Void seems unequivocal, while () seems to beg for a context to be fully understood

Regards

···

On Apr 22, 2016, at 8:28 PM, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

On Apr 22, 2016, at 12:08 PM, Vladimir.S via swift-evolution <swift-evolution@swift.org> wrote:
About the "Void".. I'm +1 on this idea, but asking myself if we can freely remove 'Void' from our language at all without any problem? Can't find the answer. It seems like we can, IMO using the syntax like () -> () is OK, clear and explicit, especially in "functional" word.

I like having Void as a typealias of (), and would prefer to retain it in the language if possible.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

We can disallow putting types in parentheses in single-element tuple meaning.
For example, (Int) -> (Double) will be illegal because of (Double).
(Int) -> (Double) -> Bool will be legal, because parentheses mean function
type here.
(Int) -> () will be legal, because () means Void here.
This can be theme of a separate proposal.

Just to clarify the proposal:

1. Disallow putting types in parentheses in single-element tuple meaning
wrong : (Int) -> (Double)
correct: (Int) -> Double
wrong: (Int) -> (Double) -> (Bool)
correct: (Int) -> (Double) -> Bool
* this rule also affects Void:
wrong: (Int) -> (Void)
correct: (Int) -> Void
wrong: (Int) -> (Double) -> (Void)
correct: (Int) -> (Double) -> Void
but correct: (Int) -> (Void) -> Void

2. Where it is allowed to have (Void) as parameters declaration, disallow putting (Void) in parentheses
wrong: (Int) -> ((Void)) -> Int
correct: (Int) -> (Void) -> Int

3. Disallow putting empty tuple () in parentheses
wrong: ((())) -> Int
correct: () -> Int
wrong: () -> ((()))
correct: () -> ()

Correct?

···

On 23.04.2016 0:52, Антон Жилин wrote:

- Anton

On 22.04.16, Vladimir.S wrote:

What I really don't like is that we can have all this:
func f1() -> (Void) {..}
func f2(Void) -> ((Void)) {..}
func f3() -> (((()))) {..}
func f4(((Void))) -> (Void) {..}
func f5() -> ((Void)) {..}
func f6((())) -> (((()))) {..}
and all is equivalent for
func f() -> () {..}

Void seems unequivocal, while () seems to beg for a context to be fully
understood

Personally I don't insist to remove the Void, but actually I'd prefer to choose some only one variant how we can express an emtpy result. IMO there is something wrong for me if we have
func f1() -> () {...}
func f2() -> () {...}
in one source file and have
func fM() -> Void {..}
func fN() -> Void {..}
in another. Additionally this will cause questions of those who's new in Swift. But OK. Not a huge problem.

What I really don't like is that we can have all this:
func f1() -> (Void) {..}
func f2(Void) -> ((Void)) {..}
func f3() -> (((()))) {..}
func f4(((Void))) -> (Void) {..}
func f5() -> ((Void)) {..}
func f6((())) -> (((()))) {..}
and all is equivalent for
func f() -> () {..}

Why(what for) this all is possible? I'd like to remove this weird "feature" from Swift. Lets say compilation error if we have () in () or Void in (). Opinions?

···

On 22.04.2016 22:27, L. Mihalkovic wrote:

Regards

On Apr 22, 2016, at 8:28 PM, Erica Sadun via swift-evolution > <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Apr 22, 2016, at 12:08 PM, Vladimir.S via swift-evolution >>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
About the "Void".. I'm +1 on this idea, but asking myself if we can
freely remove 'Void' from our language at all without any problem? Can't
find the answer. It seems like we can, IMO using the syntax like () ->
() is OK, clear and explicit, especially in "functional" word.

I like having Void as a typealias of (), and would prefer to retain it in
the language if possible.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

The thing is, Void is a typealias for ()

Therefore the impermissible:
(()) -> ()

Is identical to:
(Void) -> ()

So to follow these rules, it must instead be:
Void -> ()

… and we’re back to T1 -> T2

: )

···

On 22 Apr 2016, at 23:43, Vladimir.S via swift-evolution <swift-evolution@swift.org> wrote:

3. Disallow putting empty tuple () in parentheses

Yes, I believe we all know that Void actually is () and yes, there probably some difficulties in implementation of the rules.

The main question right now, as I see it, if we (most of us) agree with these rules in general. And then, we can think/ask if such rules could be implemented by core team in compiller/parser/etc

Personally I think we need to have just () or just Void, but I feel like most of us does not support this idea.

···

On 23.04.2016 1:58, Alan Skipp wrote:

On 22 Apr 2016, at 23:43, Vladimir.S via swift-evolution <swift-evolution@swift.org> wrote:

3. Disallow putting empty tuple () in parentheses

The thing is, Void is a typealias for ()

Therefore the impermissible:
(()) -> ()

Is identical to:
(Void) -> ()

So to follow these rules, it must instead be:
Void -> ()

… and we’re back to T1 -> T2

: )