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


(Anton Zhilin) #1

Therefore the impermissible:
(()) -> () Is identical to:
(Void) -> () So to follow these rules, it must instead be:
Void -> () … and we’re back to T1 -> T2 :* )*

Wrong! If we enforce parentheses in function types, we won't be able to write

Void -> ()

Parentheses will be required on the grammar level. The correct way to
write this will be:

() -> () or () -> Void

The following will be legal:

(Void) -> () and (()) -> ()

It is a function that takes a single parameter () and returns ().

I additionally propose that the following should be illegal, because
additional parentheses aren't needed there:

((())) -> () and () -> (()) and just (Int) and (())

Hope it cleared up things a little bit.

- Anton


(Haravikk) #2

While I know it might be a bit strange to have different rules for each side, I think I prefer empty brackets on the left and Void on the right, but in combination with required parenthesis on the left. So we’d have:

  () -> Void // yes
  Void -> () // no
  () -> () // no (rhs interpreted as empty tuple which is not allowed)
  () -> Int // yes
  Int -> Void // no (lhs no parens)
  (Int) -> Void // yes

I think the parenthesis helps to highlight that it’s a function/closure, I think it’s also clearer for cases like:

  ((Int, String)) -> Void // this is a closure taking a two-part tuple
  (Int, String) -> Void // this is definitely a closure taking an Int and a String

···

On 23 Apr 2016, at 11:47, Антон Жилин via swift-evolution <swift-evolution@swift.org> wrote:

Therefore the impermissible:
(()) -> () Is identical to:
(Void) -> () So to follow these rules, it must instead be:
Void -> () … and we’re back to T1 -> T2 : )

Wrong! If we enforce parentheses in function types, we won't be able to write
Void -> ()
Parentheses will be required on the grammar level. The correct way to write this will be:
() -> () or () -> Void
The following will be legal:
(Void) -> () and (()) -> ()
It is a function that takes a single parameter () and returns ().
I additionally propose that the following should be illegal, because additional parentheses aren't needed there:
((())) -> () and () -> (()) and just (Int) and (())
Hope it cleared up things a little bit.
- Anton
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Chris Eidhof) #3

(Sorry to be hijacking a different subthread, but I only just subscribed
again to the mailing list)

I understand why the proposal has its benefits. Yet, if we look at the
SE-0009 rationale, we could apply much of that as an argument against this
proposal, e.g. "anything that is widely repeated becomes invisible.". To
me, it feel like extra syntax where the -> is already making it very clear
that we're dealing with a function. I can understand why people would want
to enforce parenthesised types in their code bases, but to me, it feels
like clutter. I don't have any other strong rationales, adding the
parentheses feels superfluous to me, but I'm sure that I can live with it,
too.

···

--
Chris Eidhof


(Chris Lattner) #4

FWIW, it *does* make sense for there to be rules on both sides. On the right is a “type” on the left is an “argument list”, which is more general than a type already (e.g. each argument can contain inout, @autoclosure, etc).

-Chris

···

On Apr 23, 2016, at 6:01 AM, Haravikk via swift-evolution <swift-evolution@swift.org> wrote:

While I know it might be a bit strange to have different rules for each side, I think I prefer empty brackets on the left and Void on the right, but in combination with required parenthesis on the left.


(Vladimir) #5

.. To me, it feel like extra syntax where the -> is already making it

very clear that we're dealing with a function...

Can't agree with you.

I don't think it's "very clear" where the function and where is result type here:

Int -> String -> Void -> Float

in compare to this:

(Int) -> (String) -> (Void) -> Float

Int/String/Void - are parameters, not result type, as first result type is
(String) -> (Void) -> Float
then
(Void) -> Float
then
Float

Also, as described in proposal, if we can omit parenthesis then we have a question if

(Int, Int) -> Void

is a tuple->Void or func with 2 arguments? as we also can have

((Int,Int)) -> Void which is tuple -> Void

Please look at this code :

func foo(_ : (x: Int, y: Int)) -> Int {
     return 1
}

typealias FooType1 = (Int,Int) -> Int // so, what does this mean?? tuple to Int or 2 params to Int ?
typealias FooType2 = (((Int,Int))) -> Int

let bar : FooType1 = foo // ? will bar accept just tuple or just two params?
let bar2 : FooType2 = foo // ? the same question

let z = (1,2)

foo(z)
//foo(1,2) // ERROR : extra argument in call

bar(z) // no problems
bar(1, 2) // no problems

bar2(z)
// but
//bar2(1,2) // ERROR: extra argument in call

Were you confused by the FooType1 declaration?

···

On 24.04.2016 9:18, Chris Eidhof via swift-evolution wrote:

(Sorry to be hijacking a different subthread, but I only just subscribed
again to the mailing list)

I understand why the proposal has its benefits. Yet, if we look at the
SE-0009 rationale, we could apply much of that as an argument against this
proposal, e.g. "anything that is widely repeated becomes invisible.". To
me, it feel like extra syntax where the -> is already making it very clear
that we're dealing with a function. I can understand why people would want
to enforce parenthesised types in their code bases, but to me, it feels
like clutter. I don't have any other strong rationales, adding the
parentheses feels superfluous to me, but I'm sure that I can live with it, too.

--
Chris Eidhof

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