[Review] SE-0110: Distinguish between single-tuple and multiple-argument function types


(Chris Lattner) #1

Hello Swift community,

The review of "SE-0110: Distinguish between single-tuple and multiple-argument function types" begins now and runs through July 4. The proposal is available here:

  https://github.com/apple/swift-evolution/blob/master/proposals/0110-distingish-single-tuple-arg.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.

What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and contribute to 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,

-Chris Lattner
Review Manager


(Guillaume Lessard) #2

* What is your evaluation of the proposal?

Positive. I thought this was a bug, post SE-0029.

* 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?

No. (n/a?)

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

Quick read; also felt the surprise.

Guillaume Lessard


(Sean Heber) #3

The review of "SE-0110: Distinguish between single-tuple and multiple-argument function types" begins now and runs through July 4. The proposal is available here:

  https://github.com/apple/swift-evolution/blob/master/proposals/0110-distingish-single-tuple-arg.md

  * What is your evaluation of the proposal?

+1 - I’ve encountered this a number of times and it’s always been confusing. I’m not sure the proposal is clear on what happens if you don’t actually name your parameters, though. I assume $0, $1, $2, etc are created automatically as expected? Am I required to then *use* all unnamed parameters for this to work? Ideally I would not have to and this would work:

let fn2 : (Int, Int) -> Int = { return $1 }

I assume this is the intent - but the proposal might do with some clarification on that point.

  * 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?

I think most languages would probably do it this way?

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

Mostly a quick glance.

l8r
Sean


(Matthew Johnson) #4

  * What is your evaluation of the proposal?

+1. This solves something that I find a bit annoying.

  * 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?
  * How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

Quick glance

···

More information about the Swift evolution process is available at

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

Thank you,

-Chris Lattner
Review Manager

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


(Paul Cantrell) #5

  * What is your evaluation of the proposal?

+1 Yes please.

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

Tuple :left_right_arrow:︎ arg conversion magic as it stands in the language is currently more confusing than useful. I’m in favor of all efforts to remove such magic, and hoping for future features that are both more explicit and more robust.

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

Yes. The tuple/arg distinction grows ever stronger.

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

Many languages do just fine forcing individual access to arguments (i.e. no args tuples at all).

It is useful to be able to forward args en masse or call arbitrary functions with a single tuple, but Swift’s current functionality doesn’t really do this very well in practice. If we wanted either the higher-order meta-ness of functional languages or the fungibility of Javascript’s arguments var, Swift’s current behavior is not the starting point I’d choose for that.

We aren’t losing much with this proposal, either in current capability or room for future expansion.

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

Only a quick skim.

P


(Taras Zakharko) #6

  * What is your evaluation of the proposal?

+1

  * 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?
  * How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

A glance


(David Hart) #7

  * What is your evaluation of the proposal?

+1. The behaviour we are calrifying has always been fairly confusing to me. I think it comes from when arguments and tuples were semantically equivalent. Now that this is not the case anymore, this proposal seems logical.

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

Yes, lets simplify the language so we can build great stuff upon it.

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

Yes, lets simplify this tuple madness.

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

No.

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

Quick read.


(Vladimir) #8

Just want to brought some things/questions that was not reflected in proposal and that I think should be mentioned:

1. Should we be able to have such syntax to de-couple tuple's values in parameter of closure:

let a : ((Int, Int, Int)) -> Int = { ((x, y, z)) in return x + y + z }

or only as single parameter

let a : ((Int, Int, Int)) -> Int = { x in return x.0 + x.1 + x.2 }

2. Currently type of `(Int,Int)->()` is actually `((Int,Int))->()`

typealias t1 = (Int, Int) -> Int
print(t1.self) // ((Int, Int)) -> Int

the proposal should change this to:

print(t1.self) // (Int, Int) -> Int
where `((Int, Int)) -> Int` means one tuple argument

3. It seems like we should keep the ability to explicitly convert one function type to another as some(many?) code can depend on this current behavior and so we need a way to convert old code to new.

I.e. I think such construction should work:

var a : ((Int, Int, Int)) -> Int = { x in return x.0 + x.1 + x.2 }

a = { x, y, z in return x + y + z} as ((Int, Int, Int)) -> Int

and

var b : (Int, Int, Int) -> Int = { x, y, z in return x + y + z }

b = { x in return x.0 + y.1 + z.2} as (Int, Int, Int) -> Int

Opinions/thoughts?

···

On 30.06.2016 21:22, Chris Lattner via swift-evolution wrote:

Hello Swift community,

The review of "SE-0110: Distinguish between single-tuple and multiple-argument function types" begins now and runs through July 4. The proposal is available here:

  https://github.com/apple/swift-evolution/blob/master/proposals/0110-distingish-single-tuple-arg.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.

What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and contribute to 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,

-Chris Lattner
Review Manager

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


(Daniel Duan) #9

Chris Lattner via swift-evolution <swift-evolution@...> writes:

I think there's an edge case that needs consideration: when there's zero
expected arguments and the '_' parameter is used:

let f: () -> Void = { _ in }

According to the proposal, this is syntactically incorrect ( 0 != 1 ). But it
is legal now since '_' matches up with the empty tuple. Is there value to keep
it legal?

Either way, this may remain an implementation detail. But it might be
beneficial to make it explicit in the proposal.

- Daniel


(James Froggatt) #10

Somehow managed to post in the wrong thread, sorry.

See:
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160627/023221.html

From James F

···

On 30 Jun 2016, at 19:22, Chris Lattner <clattner@apple.com> wrote:

Hello Swift community,

The review of "SE-0110: Distinguish between single-tuple and multiple-argument function types" begins now and runs through July 4. The proposal is available here:

   https://github.com/apple/swift-evolution/blob/master/proposals/0110-distingish-single-tuple-arg.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.

What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and contribute to 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,

-Chris Lattner
Review Manager

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


(Austin Zheng) #11

#1 was discussed in this thread:
http://thread.gmane.org/gmane.comp.lang.swift.evolution/16190. According to
Chris, "FWIW, Swift 1 supported tuple destructuring in parameter lists, and
we took it out to simplify the language and eliminate special cases."

#2 may or may not naturally fall out of fixing the ambiguity. If it
doesn't, the proposal should definitely add it.

For #3, I would personally take the same approach as when tuple splat and
explicit currying were removed: it's pretty easy to manually write a
wrapper to convert between the old form and new form, so explicit bridging
support isn't worthwhile:

func tupleize<T, U, V, R>(_ original: (T, U, V) -> R) -> ((T, U, V)) -> R {
  return { x in
    return original(x.0, x.1, x.2)
  }
}

Best,
Austin

···

On Thu, Jun 30, 2016 at 2:02 PM, Vladimir.S via swift-evolution < swift-evolution@swift.org> wrote:

Just want to brought some things/questions that was not reflected in
proposal and that I think should be mentioned:

1. Should we be able to have such syntax to de-couple tuple's values in
parameter of closure:

let a : ((Int, Int, Int)) -> Int = { ((x, y, z)) in return x + y + z }

or only as single parameter

let a : ((Int, Int, Int)) -> Int = { x in return x.0 + x.1 + x.2 }

2. Currently type of `(Int,Int)->()` is actually `((Int,Int))->()`

typealias t1 = (Int, Int) -> Int
print(t1.self) // ((Int, Int)) -> Int

the proposal should change this to:

print(t1.self) // (Int, Int) -> Int
where `((Int, Int)) -> Int` means one tuple argument

3. It seems like we should keep the ability to explicitly convert one
function type to another as some(many?) code can depend on this current
behavior and so we need a way to convert old code to new.

I.e. I think such construction should work:

var a : ((Int, Int, Int)) -> Int = { x in return x.0 + x.1 + x.2 }

a = { x, y, z in return x + y + z} as ((Int, Int, Int)) -> Int

and

var b : (Int, Int, Int) -> Int = { x, y, z in return x + y + z }

b = { x in return x.0 + y.1 + z.2} as (Int, Int, Int) -> Int

Opinions/thoughts?

On 30.06.2016 21:22, Chris Lattner via swift-evolution wrote:

Hello Swift community,

The review of "SE-0110: Distinguish between single-tuple and
multiple-argument function types" begins now and runs through July 4. The
proposal is available here:

https://github.com/apple/swift-evolution/blob/master/proposals/0110-distingish-single-tuple-arg.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.

What goes into a review?

The goal of the review process is to improve the proposal under review
through constructive criticism and contribute to 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,

-Chris Lattner
Review Manager

_______________________________________________
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


(Vladimir) #12

#1 was discussed in this
thread: http://thread.gmane.org/gmane.comp.lang.swift.evolution/16190.
According to Chris, "FWIW, Swift 1 supported tuple destructuring in
parameter lists, and we took it out to simplify the language and eliminate
special cases."

OK. Got it.

#2 may or may not naturally fall out of fixing the ambiguity. If it
doesn't, the proposal should definitely add it.

I just think that it is worth to mention how the function type with multiply arguments represented currently.

For #3, I would personally take the same approach as when tuple splat and
explicit currying were removed: it's pretty easy to manually write a
wrapper to convert between the old form and new form, so explicit bridging
support isn't worthwhile:

func tupleize<T, U, V, R>(_ original: (T, U, V) -> R) -> ((T, U, V)) -> R {
  return { x in
    return original(x.0, x.1, x.2)
  }
}

Currently there could be a lot of code that relies on current behavior, so IMO we should provide a easy way to convert to Swift 3.0. I feel like explicit bridging the best solution here.
But from other point of view, Swift 3 is source breaking release anyway and one will just need to change tuple to list of parameters (or vice-versa) in code to conform to correct type of function.

···

On 01.07.2016 0:17, Austin Zheng wrote:

Best,
Austin

On Thu, Jun 30, 2016 at 2:02 PM, Vladimir.S via swift-evolution > <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

    Just want to brought some things/questions that was not reflected in
    proposal and that I think should be mentioned:

    1. Should we be able to have such syntax to de-couple tuple's values in
    parameter of closure:

    let a : ((Int, Int, Int)) -> Int = { ((x, y, z)) in return x + y + z }

    or only as single parameter

    let a : ((Int, Int, Int)) -> Int = { x in return x.0 + x.1 + x.2 }

    2. Currently type of `(Int,Int)->()` is actually `((Int,Int))->()`

    typealias t1 = (Int, Int) -> Int
    print(t1.self) // ((Int, Int)) -> Int

    the proposal should change this to:

    print(t1.self) // (Int, Int) -> Int
    where `((Int, Int)) -> Int` means one tuple argument

    3. It seems like we should keep the ability to explicitly convert one
    function type to another as some(many?) code can depend on this current
    behavior and so we need a way to convert old code to new.

    I.e. I think such construction should work:

    var a : ((Int, Int, Int)) -> Int = { x in return x.0 + x.1 + x.2 }

    a = { x, y, z in return x + y + z} as ((Int, Int, Int)) -> Int

    and

    var b : (Int, Int, Int) -> Int = { x, y, z in return x + y + z }

    b = { x in return x.0 + y.1 + z.2} as (Int, Int, Int) -> Int

    Opinions/thoughts?

    On 30.06.2016 21:22, Chris Lattner via swift-evolution wrote:

        Hello Swift community,

        The review of "SE-0110: Distinguish between single-tuple and
        multiple-argument function types" begins now and runs through July
        4. The proposal is available here:

        https://github.com/apple/swift-evolution/blob/master/proposals/0110-distingish-single-tuple-arg.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.

        What goes into a review?

        The goal of the review process is to improve the proposal under
        review through constructive criticism and contribute to 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,

        -Chris Lattner
        Review Manager

        _______________________________________________
        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


(Vladimir) #13

Chris Lattner via swift-evolution <swift-evolution@...> writes:

I think there's an edge case that needs consideration: when there's zero
expected arguments and the '_' parameter is used:

let f: () -> Void = { _ in }

As I understand current syntax and logic, there is *one* expected argument : Void. This is why we can call f(()). But we are allowed to omit that empty tuple parameter in syntax(on caller side and in function parameter list definition). So, IMO or this should be leaved as is, or we should move away from association between Void and "emptiness" of parameters(I don't understand if this is possible).

If we'll disallow this, will that be allowed:

func foo(_ x: Void) { print(x) }

foo()

and then question regarding

typealias MyFunc<T> = (T) -> Void

let myfunc1 : MyFunc<Int> = {i in print(i)}
let myfunc2 : MyFunc<String> = {s in print(s)}
let myfunc3 : MyFunc<Void> = {_ in print("nothing")}

Probably there is no problem with current behavior for empty tuple(Void) as soon as *one* parameter will be mapped to the same *one* argument(or zero arguments for this very special case).

Btw, don't we want to stop these games with recursive empty tuples:

foo(())
foo(((())))

···

On 02.07.2016 1:49, Daniel Duan via swift-evolution wrote:

According to the proposal, this is syntactically incorrect ( 0 != 1 ). But it
is legal now since '_' matches up with the empty tuple. Is there value to keep
it legal?

Either way, this may remain an implementation detail. But it might be
beneficial to make it explicit in the proposal.

- Daniel

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


(TJ Usiyan) #14

+1 if SE-0111 is accepted. 0 otherwise.

···

On Fri, Jul 1, 2016 at 7:34 PM, Vladimir.S via swift-evolution < swift-evolution@swift.org> wrote:

On 02.07.2016 1:49, Daniel Duan via swift-evolution wrote:

Chris Lattner via swift-evolution <swift-evolution@...> writes:

I think there's an edge case that needs consideration: when there's zero
expected arguments and the '_' parameter is used:

let f: () -> Void = { _ in }

As I understand current syntax and logic, there is *one* expected argument
: Void. This is why we can call f(()). But we are allowed to omit that
empty tuple parameter in syntax(on caller side and in function parameter
list definition). So, IMO or this should be leaved as is, or we should move
away from association between Void and "emptiness" of parameters(I don't
understand if this is possible).

If we'll disallow this, will that be allowed:

func foo(_ x: Void) { print(x) }

foo()

and then question regarding

typealias MyFunc<T> = (T) -> Void

let myfunc1 : MyFunc<Int> = {i in print(i)}
let myfunc2 : MyFunc<String> = {s in print(s)}
let myfunc3 : MyFunc<Void> = {_ in print("nothing")}

Probably there is no problem with current behavior for empty tuple(Void)
as soon as *one* parameter will be mapped to the same *one* argument(or
zero arguments for this very special case).

Btw, don't we want to stop these games with recursive empty tuples:

foo(())
foo(((())))

According to the proposal, this is syntactically incorrect ( 0 != 1 ).
But it
is legal now since '_' matches up with the empty tuple. Is there value to
keep
it legal?

Either way, this may remain an implementation detail. But it might be
beneficial to make it explicit in the proposal.

- Daniel

_______________________________________________
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


(Daniel Duan) #15

Vladimir.S via swift-evolution <swift-evolution@...> writes:

Following your conclusion, should this be legal as well?

let f: () -> Void = { x in print(x) } // f() prints "()"
let f: (Int) -> Void = { x in print(x) } // f(5) prints "5"

In other words, "0 argument" is an impossible scenario?


(Vladimir) #16

Vladimir.S via swift-evolution <swift-evolution@...> writes:

Following your conclusion, should this be legal as well?

let f: () -> Void = { x in print(x) } // f() prints "()"
let f: (Int) -> Void = { x in print(x) } // f(5) prints "5"

In other words, "0 argument" is an impossible scenario?

I don't see problems here. ()->Void means (Void)->Void, there *is* one parameter of Void type, which we can omitted as it is empty tuple. So, if you want you can write f(()) or or let z = (); f(z); or just f(), so in closure definition you can have one argument or can have 0 defined arguments if the only argument is of type Void.

It is not the same as be able to accept non-empty tuple when a list of parameters are expected or vice-versa.

I don't think we should move away(if it is possible at all) from representing zero-argument by empty tuple(Void). This looks like good and useful thing in Swift, especially in functional programming and when working with generics (we can pass parameter(of type void) even when call function with 0 defined arguments).

I actually wonder what should be a type of such function:

func f1() {}
print(f1.dynamicType)

Now it is `(()) -> ()`. Should it be `() -> ()`? Seems like no - it actually take 1 argument(empty tuple, Void) and returns empty tuple. So the `() -> ()` *declaration* just still be just an alias for real type `(()) -> ()`. IMO.

···

On 02.07.2016 4:20, Daniel Duan via swift-evolution wrote:

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


(Haravikk) #17

I think the issue is that it's unexpected; I would expect () -> Void to mean no arguments at all, rather than one argument that is Void, as I can't really envision any cases where I'd need the latter. I think it's reasonable that for those who can, that they use (()) -> Void to clarify that this is the case, which I think fits well with Swift's general philosophy of avoiding mistakes, even if this is probably a minor one, it removes an area of confusion or inconsistency.

···

On 3 Jul 2016, at 13:02, Vladimir.S via swift-evolution <swift-evolution@swift.org> wrote:

On 02.07.2016 4:20, Daniel Duan via swift-evolution wrote:

Vladimir.S via swift-evolution <swift-evolution@...> writes:

Following your conclusion, should this be legal as well?

let f: () -> Void = { x in print(x) } // f() prints "()"
let f: (Int) -> Void = { x in print(x) } // f(5) prints "5"

In other words, "0 argument" is an impossible scenario?

I don't see problems here. ()->Void means (Void)->Void, there *is* one parameter of Void type, which we can omitted as it is empty tuple. So, if you want you can write f(()) or or let z = (); f(z); or just f(), so in closure definition you can have one argument or can have 0 defined arguments if the only argument is of type Void.

It is not the same as be able to accept non-empty tuple when a list of parameters are expected or vice-versa.

I don't think we should move away(if it is possible at all) from representing zero-argument by empty tuple(Void). This looks like good and useful thing in Swift, especially in functional programming and when working with generics (we can pass parameter(of type void) even when call function with 0 defined arguments).

I actually wonder what should be a type of such function:

func f1() {}
print(f1.dynamicType)

Now it is `(()) -> ()`. Should it be `() -> ()`? Seems like no - it actually take 1 argument(empty tuple, Void) and returns empty tuple. So the `() -> ()` *declaration* just still be just an alias for real type `(()) -> ()`. IMO.


(Jordan Rose) #18

I already said this on the bug you filed, but I disagree quite strongly with this interpretation, based on SE-0029 <https://github.com/apple/swift-evolution/blob/master/proposals/0029-remove-implicit-tuple-splat.md>SE-002 <https://github.com/apple/swift-evolution/blob/master/proposals/0029-remove-implicit-tuple-splat.md>9. IMO, going from (()) to () is a form of tuple splat.

Jordan

···

On Jul 3, 2016, at 5:02, Vladimir.S via swift-evolution <swift-evolution@swift.org> wrote:

On 02.07.2016 4:20, Daniel Duan via swift-evolution wrote:

Vladimir.S via swift-evolution <swift-evolution@...> writes:

Following your conclusion, should this be legal as well?

let f: () -> Void = { x in print(x) } // f() prints "()"
let f: (Int) -> Void = { x in print(x) } // f(5) prints "5"

In other words, "0 argument" is an impossible scenario?

I don't see problems here. ()->Void means (Void)->Void, there *is* one parameter of Void type, which we can omitted as it is empty tuple. So, if you want you can write f(()) or or let z = (); f(z); or just f(), so in closure definition you can have one argument or can have 0 defined arguments if the only argument is of type Void.


(Vladimir) #19

Vladimir.S via swift-evolution <swift-evolution@...> writes:

Following your conclusion, should this be legal as well?

let f: () -> Void = { x in print(x) } // f() prints "()"
let f: (Int) -> Void = { x in print(x) } // f(5) prints "5"

In other words, "0 argument" is an impossible scenario?

I don't see problems here. ()->Void means (Void)->Void, there *is* one parameter of Void type, which we can omitted as it is empty tuple. So, if you want you can write f(()) or or let z = (); f(z); or just f(), so in closure definition you can have one argument or can have 0 defined arguments if the only argument is of type Void.

It is not the same as be able to accept non-empty tuple when a list of parameters are expected or vice-versa.

I don't think we should move away(if it is possible at all) from representing zero-argument by empty tuple(Void). This looks like good and useful thing in Swift, especially in functional programming and when working with generics (we can pass parameter(of type void) even when call function with 0 defined arguments).

I actually wonder what should be a type of such function:

func f1() {}
print(f1.dynamicType)

Now it is `(()) -> ()`. Should it be `() -> ()`? Seems like no - it actually take 1 argument(empty tuple, Void) and returns empty tuple. So the `() -> ()` *declaration* just still be just an alias for real type `(()) -> ()`. IMO.

I think the issue is that it's unexpected; I would expect () -> Void to

mean no arguments at all, rather than one argument that is Void, as I can't
really envision any cases where I'd need the latter. I think it's
reasonable that for those who can, that they use (()) -> Void to clarify
that this is the case, which I think fits well with Swift's general
philosophy of avoiding mistakes, even if this is probably a minor one, it
removes an area of confusion or inconsistency.

Well.. according to thread "[Pre-proposal] Fix function type grammar" - it is decided to *not* allow () as parameter to 0 argument function. You'll need to explicitly allow Void argument definition in function if you need this. So as I understand this question is closed.

As for use-cases, actually I was thinking about functional programming and generics: when you can pass result of previous func to next (in case of ()->() it is Void as now) or use Void as generic type to be able to call ()->() func. Otherwise you'll need wrappers f2(())->() {f1(); return ()} and so on. But probably this is not a problem and I'm just missing something.

But, then, regarding the consistency and confusion, I have a question: is it expected that func f() {..} will *return* `Void` ? I believe it is not expected exactly at the same level as Void in parameter for 0 argument function. I.e. should `-> ()` still means "returns Void" or "returns nothing" ?

···

On 03.07.2016 19:48, Haravikk wrote:

On 3 Jul 2016, at 13:02, Vladimir.S via swift-evolution <swift-evolution@swift.org> wrote:
On 02.07.2016 4:20, Daniel Duan via swift-evolution wrote:


(Daniel Duan) #20

I have a patch that implements this proposal *except* this part. (aka () -> Void means 0 argument therefore { _ in } is a mismatch).

If we were to interpret tuple and the outer paren as described in this proposal, it should be consistent everywhere, therefore requires more consideration (separate proposal) and bigger change in the compiler.

Daniel Duan

···

Sent from my iPhone

On Jul 5, 2016, at 2:07 PM, Jordan Rose <jordan_rose@apple.com> wrote:

On Jul 3, 2016, at 5:02, Vladimir.S via swift-evolution <swift-evolution@swift.org> wrote:

On 02.07.2016 4:20, Daniel Duan via swift-evolution wrote:

Vladimir.S via swift-evolution <swift-evolution@...> writes:

Following your conclusion, should this be legal as well?

let f: () -> Void = { x in print(x) } // f() prints "()"
let f: (Int) -> Void = { x in print(x) } // f(5) prints "5"

In other words, "0 argument" is an impossible scenario?

I don't see problems here. ()->Void means (Void)->Void, there *is* one parameter of Void type, which we can omitted as it is empty tuple. So, if you want you can write f(()) or or let z = (); f(z); or just f(), so in closure definition you can have one argument or can have 0 defined arguments if the only argument is of type Void.

I already said this on the bug you filed, but I disagree quite strongly with this interpretation, based on SE-0029. IMO, going from (()) to () is a form of tuple splat.

Jordan