Variadics through tuples


(James Froggatt) #1

Currently, the following code is allowed:

//function application operator
infix operator => {}
func =><In, Out>(a: In, b: In -> Out) -> Out {
    return try b(a)
}

infix operator ?=> {}
func ?=><In, Out>(a: In?, b: In -> Out?) -> Out? {
    if let unwrapped = a {
        return try b(a)
    }
    return nil
}

//some defined functions

func defaultDestination() -> (x: Int, y: Int)
func loadedDestination() -> (x: Int, y: Int)?
func moveTo(x: Int, y: Int)

//actual code

defaultDestination() => moveTo
loadedDestination() ?=> moveTo ?? print("load failed")

//code without functional chaining

let point = defaultDestination()
moveTo(x: point.x, y: point.y)

if let loaded = loadedDestination() {
    moveTo(x: loaded.x, y: loaded.y)
} else {
    print("load failed")
}

I'm expecting this to stop working at some point in Swift 3's development, since it is related to tuple splat. I've heard talk of tuple splat returning in the future through an operator, with the stand-in syntax:

moveTo(*defaultDestination())

So, how would a functional chaining operator work under these conditions? It would require a second variadic splat operator:

defaultDestination() => *moveTo(x:y:)

The motivation for removing the standard form of tuple splat is that the calling syntax looks like an overload. But in this case, an explicit splat operator doesn't add any clarity, since the function being referred to can be unambiguous.

So, my question is whether this is worth removing full support for in the first place. This behaviour can be make to fit Swift 3's distinction of parameter lists and tuples, by applying specific rules to the existing behaviour to create a lightweight variadics system:

takesAClosure<T>(_: (T) -> ()) //closure explicitly takes a single parameter

takesAClosure<T>(_: T -> ()) //closure takes any number of parameters

takesAClosure<T>(_: T, _: T -> ()) //closure takes any number of parameters, but must have a parameter list which can be directly represented as a tuple

Either way, I'm hoping whatever syntax ends up chosen for variadics is nearly as simple to use as tuple splat has been, tuples are (literally) made for this purpose. I'll be disappointed to see this feature removed.


(Vladimir) #2

Yes, I expect that with the implemented proposal SE-0110 your code will not compile because `moveTo` has type `(Int, Int)->Void` and not required `((Int, Int))->Void`. You'll need to change the moveTo to accept tuple argument or use some function/operator to transform argument list parametrized function to function with tuple argument.

For example (this compiles now and IMO should after SE-0110 implemented, if accepted):

//function application operator
infix operator => {}
func =><In, Out>(a: In, b: (In) -> Out) -> Out {
     return try b(a)
}

infix operator ?=> {}
func ?=><In, Out>(a: In?, b: (In) -> Out?) -> Out? {
     if let unwrapped = a {
         return try b(unwrapped)
     }
     return nil
}

//some defined functions

func defaultDestination() -> (x: Int, y: Int) {return (1,1) }
func loadedDestination() -> (x: Int, y: Int)? {return nil }

// ---- Variant 1 ----
func moveTo1(point: (x: Int, y: Int)) {print("move1 to: ", point.x, point.y)}

// ---- Variant 2 ----
func moveTo2(x: Int, y: Int) {print("move2 to: ", x, y)}

func tupleize<T,U,V>(_ f: (T,U)->V ) -> ( ((T, U))->V ) {
     return { tu in return f(tu.0, tu.1) }
}

//actual code

defaultDestination() => moveTo1
(loadedDestination() ?=> moveTo1) ?? print("load1 failed")

defaultDestination() => tupleize(moveTo2)
(loadedDestination() ?=> tupleize(moveTo2)) ?? print("load2 failed")

If we'll have such `tupleize` as built-in operator, then things will be even better. Don't see any problem here just like you, for example, don't expect function of (Int, (Int, String))->() will be accepted where (Int, Int, String)->() is required an so on. List of function arguments is not tuple at these days and so IMO only explicit conversion can exist to accept second when first is required and vice-versa. But I'm storng +1 to have such handy convertion operator.

···

On 01.07.2016 17:16, James Froggatt via swift-evolution wrote:

Currently, the following code is allowed:

//function application operator
infix operator => {}
func =><In, Out>(a: In, b: In -> Out) -> Out {
    return try b(a)
}

infix operator ?=> {}
func ?=><In, Out>(a: In?, b: In -> Out?) -> Out? {
    if let unwrapped = a {
        return try b(a)
    }
    return nil
}

//some defined functions

func defaultDestination() -> (x: Int, y: Int)
func loadedDestination() -> (x: Int, y: Int)?
func moveTo(x: Int, y: Int)

//actual code

defaultDestination() => moveTo
loadedDestination() ?=> moveTo ?? print("load failed")

//code without functional chaining

let point = defaultDestination()
moveTo(x: point.x, y: point.y)

if let loaded = loadedDestination() {
    moveTo(x: loaded.x, y: loaded.y)
} else {
    print("load failed")
}

I'm expecting this to stop working at some point in Swift 3's development, since it is related to tuple splat. I've heard talk of tuple splat returning in the future through an operator, with the stand-in syntax:

moveTo(*defaultDestination())

So, how would a functional chaining operator work under these conditions? It would require a second variadic splat operator:

defaultDestination() => *moveTo(x:y:)

The motivation for removing the standard form of tuple splat is that the calling syntax looks like an overload. But in this case, an explicit splat operator doesn't add any clarity, since the function being referred to can be unambiguous.

So, my question is whether this is worth removing full support for in the first place. This behaviour can be make to fit Swift 3's distinction of parameter lists and tuples, by applying specific rules to the existing behaviour to create a lightweight variadics system:

takesAClosure<T>(_: (T) -> ()) //closure explicitly takes a single parameter

takesAClosure<T>(_: T -> ()) //closure takes any number of parameters

takesAClosure<T>(_: T, _: T -> ()) //closure takes any number of parameters, but must have a parameter list which can be directly represented as a tuple

Either way, I'm hoping whatever syntax ends up chosen for variadics is nearly as simple to use as tuple splat has been, tuples are (literally) made for this purpose. I'll be disappointed to see this feature removed.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(James Froggatt) #3

Thanks for the response. I understand function overloading is possible, but it isn't nearly as convinient.

However, if explicit conversion is the way forward, then in the spirit of keeping backwards-compatibility in some form, we could simply allow this:

let paramsClosure: (Int, Int) -> () = …
let tupleClosure = paramsClosure as ((Int, Int)) -> ()

The ‘as’ operator is already used for various type system magic (like converting T to Optional<T>), so this seems fairly natural. There shouldn't be any ambiguity, since overloads taking tuples would have either different labels or type signature:

moveTo(x: Int, y: Int)
moveTo(_: (x: Int, y: Int)) //sneaky
moveTo(x: (x: Int, y: Int), y: Int) //plain dumb

let a = moveTo(x:y:)
let b = moveTo(_:slight_smile:
let c = moveTo(x:y:) as ((x: Int, y: Int), Int) -> () //cast needed, same as for any type-based overload

let d = moveTo(x:y:) as ((Int, Int)) -> () //unambiguously the first function

Since this is clearly an explicit cast, which doesn't fall under the ‘remove implicit tuple splat’ proposal, can we explicity decide to keep this?

A splat operator would then be user-definable (meaning fewer magic operators), just being applied to the function rather than the arguments:

moveTo(x: point.x, y: point.y)

(moveTo*)(point)

So, rather than a language addition, or even a modification of an existing proposal, this is something which sensibly should still be allowed even once ‘implicit tuple splat’ is removed. We'd actually be losing a decent feature if we remove this completely, as is acknowledged by the suggestion of an explicit splat operator in the proposal.

From James F

PS: Actually, I'm surprised your code compiles, since I removed the ‘rethrows’ decoration from the operator's function signature for brevity, but left the ‘try’ in the implementation itself. Does Swift promote non-throwing functions to throwing ones like that? I have to double-check I don't have stray ‘try’s lying around.

···

On 1 Jul 2016, at 19:15, Vladimir.S <svabox@gmail.com> wrote:

Yes, I expect that with the implemented proposal SE-0110 your code will not compile because `moveTo` has type `(Int, Int)->Void` and not required `((Int, Int))->Void`. You'll need to change the moveTo to accept tuple argument or use some function/operator to transform argument list parametrized function to function with tuple argument.

For example (this compiles now and IMO should after SE-0110 implemented, if accepted):

//function application operator
infix operator => {}
func =><In, Out>(a: In, b: (In) -> Out) -> Out {
   return try b(a)
}

infix operator ?=> {}
func ?=><In, Out>(a: In?, b: (In) -> Out?) -> Out? {
   if let unwrapped = a {
       return try b(unwrapped)
   }
   return nil
}

//some defined functions

func defaultDestination() -> (x: Int, y: Int) {return (1,1) }
func loadedDestination() -> (x: Int, y: Int)? {return nil }

// ---- Variant 1 ----
func moveTo1(point: (x: Int, y: Int)) {print("move1 to: ", point.x, point.y)}

// ---- Variant 2 ----
func moveTo2(x: Int, y: Int) {print("move2 to: ", x, y)}

func tupleize<T,U,V>(_ f: (T,U)->V ) -> ( ((T, U))->V ) {
   return { tu in return f(tu.0, tu.1) }
}

//actual code

defaultDestination() => moveTo1
(loadedDestination() ?=> moveTo1) ?? print("load1 failed")

defaultDestination() => tupleize(moveTo2)
(loadedDestination() ?=> tupleize(moveTo2)) ?? print("load2 failed")

If we'll have such `tupleize` as built-in operator, then things will be even better. Don't see any problem here just like you, for example, don't expect function of (Int, (Int, String))->() will be accepted where (Int, Int, String)->() is required an so on. List of function arguments is not tuple at these days and so IMO only explicit conversion can exist to accept second when first is required and vice-versa. But I'm storng +1 to have such handy convertion operator.

On 01.07.2016 17:16, James Froggatt via swift-evolution wrote:
Currently, the following code is allowed:

//function application operator
infix operator => {}
func =><In, Out>(a: In, b: In -> Out) -> Out {
   return try b(a)
}

infix operator ?=> {}
func ?=><In, Out>(a: In?, b: In -> Out?) -> Out? {
   if let unwrapped = a {
       return try b(a)
   }
   return nil
}

//some defined functions

func defaultDestination() -> (x: Int, y: Int)
func loadedDestination() -> (x: Int, y: Int)?
func moveTo(x: Int, y: Int)

//actual code

defaultDestination() => moveTo
loadedDestination() ?=> moveTo ?? print("load failed")

//code without functional chaining

let point = defaultDestination()
moveTo(x: point.x, y: point.y)

if let loaded = loadedDestination() {
   moveTo(x: loaded.x, y: loaded.y)
} else {
   print("load failed")
}

I'm expecting this to stop working at some point in Swift 3's development, since it is related to tuple splat. I've heard talk of tuple splat returning in the future through an operator, with the stand-in syntax:

moveTo(*defaultDestination())

So, how would a functional chaining operator work under these conditions? It would require a second variadic splat operator:

defaultDestination() => *moveTo(x:y:)

The motivation for removing the standard form of tuple splat is that the calling syntax looks like an overload. But in this case, an explicit splat operator doesn't add any clarity, since the function being referred to can be unambiguous.

So, my question is whether this is worth removing full support for in the first place. This behaviour can be make to fit Swift 3's distinction of parameter lists and tuples, by applying specific rules to the existing behaviour to create a lightweight variadics system:

takesAClosure<T>(_: (T) -> ()) //closure explicitly takes a single parameter

takesAClosure<T>(_: T -> ()) //closure takes any number of parameters

takesAClosure<T>(_: T, _: T -> ()) //closure takes any number of parameters, but must have a parameter list which can be directly represented as a tuple

Either way, I'm hoping whatever syntax ends up chosen for variadics is nearly as simple to use as tuple splat has been, tuples are (literally) made for this purpose. I'll be disappointed to see this feature removed.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Vladimir) #4

Thanks for the response. I understand function overloading is possible, but it isn't nearly as convinient.

Yes, agree.

However, if explicit conversion is the way forward, then in the spirit of keeping backwards-compatibility in some form, we could simply allow this:

let paramsClosure: (Int, Int) -> () = �c
let tupleClosure = paramsClosure as ((Int, Int)) -> ()

The �eas�f operator is already used for various type system magic (like converting T to Optional<T>), so this seems fairly natural. There shouldn't be any ambiguity, since overloads taking tuples would have either different labels or type signature:

Personally I also think that we need such `as` conversions from one to another. At least because IMO there is a lot of code that already use the feature of tuple splatting.

moveTo(x: Int, y: Int)
moveTo(_: (x: Int, y: Int)) //sneaky
moveTo(x: (x: Int, y: Int), y: Int) //plain dumb

let a = moveTo(x:y:)
let b = moveTo(_:slight_smile:
let c = moveTo(x:y:) as ((x: Int, y: Int), Int) -> () //cast needed, same as for any type-based overload

let d = moveTo(x:y:) as ((Int, Int)) -> () //unambiguously the first function

Since this is clearly an explicit cast, which doesn't fall under the �eremove implicit tuple splat�f proposal, can we explicity decide to keep this?

A splat operator would then be user-definable (meaning fewer magic operators), just being applied to the function rather than the arguments:

moveTo(x: point.x, y: point.y)

(moveTo*)(point)

So, rather than a language addition, or even a modification of an existing proposal, this is something which sensibly should still be allowed even once �eimplicit tuple splat�f is removed. We'd actually be losing a decent feature if we remove this completely, as is acknowledged by the suggestion of an explicit splat operator in the proposal.

From James F

Actually I also see a solution in having both: explicit 'as' conversion and in special operator. I feel like such special operator could be important for functional programming in Swift. 'as' conversion is very verbose and you have to write it for each function again and again(or use typealias), but operator will use one compiler magic for all functions.

I believe core team should decide if they want to keep/allow such 'as' conversion in case the proposal will be accepted.

PS: Actually, I'm surprised your code compiles, since I removed the �erethrows�f decoration from the operator's function signature for brevity, but left the �etry�f in the implementation itself. Does Swift promote non-throwing functions to throwing ones like that? I have to double-check I don't have stray �etry�fs lying around.

:slight_smile: Yes, I also was surprised with just warnings in these places, but not errors. Don't know if it is a bug or not. Can someone explain ?

Hint: check compilation warnings for your code.

···

On 01.07.2016 23:55, James Froggatt wrote:

On 1 Jul 2016, at 19:15, Vladimir.S <svabox@gmail.com> wrote:

Yes, I expect that with the implemented proposal SE-0110 your code will not compile because `moveTo` has type `(Int, Int)->Void` and not required `((Int, Int))->Void`. You'll need to change the moveTo to accept tuple argument or use some function/operator to transform argument list parametrized function to function with tuple argument.

For example (this compiles now and IMO should after SE-0110 implemented, if accepted):

//function application operator
infix operator => {}
func =><In, Out>(a: In, b: (In) -> Out) -> Out {
   return try b(a)
}

infix operator ?=> {}
func ?=><In, Out>(a: In?, b: (In) -> Out?) -> Out? {
   if let unwrapped = a {
       return try b(unwrapped)
   }
   return nil
}

//some defined functions

func defaultDestination() -> (x: Int, y: Int) {return (1,1) }
func loadedDestination() -> (x: Int, y: Int)? {return nil }

// ---- Variant 1 ----
func moveTo1(point: (x: Int, y: Int)) {print("move1 to: ", point.x, point.y)}

// ---- Variant 2 ----
func moveTo2(x: Int, y: Int) {print("move2 to: ", x, y)}

func tupleize<T,U,V>(_ f: (T,U)->V ) -> ( ((T, U))->V ) {
   return { tu in return f(tu.0, tu.1) }
}

//actual code

defaultDestination() => moveTo1
(loadedDestination() ?=> moveTo1) ?? print("load1 failed")

defaultDestination() => tupleize(moveTo2)
(loadedDestination() ?=> tupleize(moveTo2)) ?? print("load2 failed")

If we'll have such `tupleize` as built-in operator, then things will be even better. Don't see any problem here just like you, for example, don't expect function of (Int, (Int, String))->() will be accepted where (Int, Int, String)->() is required an so on. List of function arguments is not tuple at these days and so IMO only explicit conversion can exist to accept second when first is required and vice-versa. But I'm storng +1 to have such handy convertion operator.

On 01.07.2016 17:16, James Froggatt via swift-evolution wrote:
Currently, the following code is allowed:

//function application operator
infix operator => {}
func =><In, Out>(a: In, b: In -> Out) -> Out {
   return try b(a)
}

infix operator ?=> {}
func ?=><In, Out>(a: In?, b: In -> Out?) -> Out? {
   if let unwrapped = a {
       return try b(a)
   }
   return nil
}

//some defined functions

func defaultDestination() -> (x: Int, y: Int)
func loadedDestination() -> (x: Int, y: Int)?
func moveTo(x: Int, y: Int)

//actual code

defaultDestination() => moveTo
loadedDestination() ?=> moveTo ?? print("load failed")

//code without functional chaining

let point = defaultDestination()
moveTo(x: point.x, y: point.y)

if let loaded = loadedDestination() {
   moveTo(x: loaded.x, y: loaded.y)
} else {
   print("load failed")
}

I'm expecting this to stop working at some point in Swift 3's development, since it is related to tuple splat. I've heard talk of tuple splat returning in the future through an operator, with the stand-in syntax:

moveTo(*defaultDestination())

So, how would a functional chaining operator work under these conditions? It would require a second variadic splat operator:

defaultDestination() => *moveTo(x:y:)

The motivation for removing the standard form of tuple splat is that the calling syntax looks like an overload. But in this case, an explicit splat operator doesn't add any clarity, since the function being referred to can be unambiguous.

So, my question is whether this is worth removing full support for in the first place. This behaviour can be make to fit Swift 3's distinction of parameter lists and tuples, by applying specific rules to the existing behaviour to create a lightweight variadics system:

takesAClosure<T>(_: (T) -> ()) //closure explicitly takes a single parameter

takesAClosure<T>(_: T -> ()) //closure takes any number of parameters

takesAClosure<T>(_: T, _: T -> ()) //closure takes any number of parameters, but must have a parameter list which can be directly represented as a tuple

Either way, I'm hoping whatever syntax ends up chosen for variadics is nearly as simple to use as tuple splat has been, tuples are (literally) made for this purpose. I'll be disappointed to see this feature removed.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(James Froggatt) #5

Thanks. I agree, a standard library operator would clearly be the preferred way to do this, at least for general use. Basing it upon the ‘as’ cast just means we don't have to have to deal with another magical operator (looking at the inability to overload ‘!’ and ‘?’), as well as easing the transition from Swift 2.

From James F

···

On 1 Jul 2016, at 22:11, Vladimir.S <svabox@gmail.com> wrote:

On 01.07.2016 23:55, James Froggatt wrote:
Thanks for the response. I understand function overloading is possible, but it isn't nearly as convinient.

Yes, agree.

However, if explicit conversion is the way forward, then in the spirit of keeping backwards-compatibility in some form, we could simply allow this:

let paramsClosure: (Int, Int) -> () = …
let tupleClosure = paramsClosure as ((Int, Int)) -> ()

The ‘as’ operator is already used for various type system magic (like converting T to Optional<T>), so this seems fairly natural. There shouldn't be any ambiguity, since overloads taking tuples would have either different labels or type signature:

Personally I also think that we need such `as` conversions from one to another. At least because IMO there is a lot of code that already use the feature of tuple splatting.

moveTo(x: Int, y: Int)
moveTo(_: (x: Int, y: Int)) //sneaky
moveTo(x: (x: Int, y: Int), y: Int) //plain dumb

let a = moveTo(x:y:)
let b = moveTo(_:slight_smile:
let c = moveTo(x:y:) as ((x: Int, y: Int), Int) -> () //cast needed, same as for any type-based overload

let d = moveTo(x:y:) as ((Int, Int)) -> () //unambiguously the first function

Since this is clearly an explicit cast, which doesn't fall under the ‘remove implicit tuple splat’ proposal, can we explicity decide to keep this?

A splat operator would then be user-definable (meaning fewer magic operators), just being applied to the function rather than the arguments:

moveTo(x: point.x, y: point.y)

(moveTo*)(point)

So, rather than a language addition, or even a modification of an existing proposal, this is something which sensibly should still be allowed even once ‘implicit tuple splat’ is removed. We'd actually be losing a decent feature if we remove this completely, as is acknowledged by the suggestion of an explicit splat operator in the proposal.

From James F

Actually I also see a solution in having both: explicit 'as' conversion and in special operator. I feel like such special operator could be important for functional programming in Swift. 'as' conversion is very verbose and you have to write it for each function again and again(or use typealias), but operator will use one compiler magic for all functions.

I believe core team should decide if they want to keep/allow such 'as' conversion in case the proposal will be accepted.

PS: Actually, I'm surprised your code compiles, since I removed the ‘rethrows’ decoration from the operator's function signature for brevity, but left the ‘try’ in the implementation itself. Does Swift promote non-throwing functions to throwing ones like that? I have to double-check I don't have stray ‘try’s lying around.

:slight_smile: Yes, I also was surprised with just warnings in these places, but not errors. Don't know if it is a bug or not. Can someone explain ?

Hint: check compilation warnings for your code.

On 1 Jul 2016, at 19:15, Vladimir.S <svabox@gmail.com> wrote:

Yes, I expect that with the implemented proposal SE-0110 your code will not compile because `moveTo` has type `(Int, Int)->Void` and not required `((Int, Int))->Void`. You'll need to change the moveTo to accept tuple argument or use some function/operator to transform argument list parametrized function to function with tuple argument.

For example (this compiles now and IMO should after SE-0110 implemented, if accepted):

//function application operator
infix operator => {}
func =><In, Out>(a: In, b: (In) -> Out) -> Out {
  return try b(a)
}

infix operator ?=> {}
func ?=><In, Out>(a: In?, b: (In) -> Out?) -> Out? {
  if let unwrapped = a {
      return try b(unwrapped)
  }
  return nil
}

//some defined functions

func defaultDestination() -> (x: Int, y: Int) {return (1,1) }
func loadedDestination() -> (x: Int, y: Int)? {return nil }

// ---- Variant 1 ----
func moveTo1(point: (x: Int, y: Int)) {print("move1 to: ", point.x, point.y)}

// ---- Variant 2 ----
func moveTo2(x: Int, y: Int) {print("move2 to: ", x, y)}

func tupleize<T,U,V>(_ f: (T,U)->V ) -> ( ((T, U))->V ) {
  return { tu in return f(tu.0, tu.1) }
}

//actual code

defaultDestination() => moveTo1
(loadedDestination() ?=> moveTo1) ?? print("load1 failed")

defaultDestination() => tupleize(moveTo2)
(loadedDestination() ?=> tupleize(moveTo2)) ?? print("load2 failed")

If we'll have such `tupleize` as built-in operator, then things will be even better. Don't see any problem here just like you, for example, don't expect function of (Int, (Int, String))->() will be accepted where (Int, Int, String)->() is required an so on. List of function arguments is not tuple at these days and so IMO only explicit conversion can exist to accept second when first is required and vice-versa. But I'm storng +1 to have such handy convertion operator.

On 01.07.2016 17:16, James Froggatt via swift-evolution wrote:
Currently, the following code is allowed:

//function application operator
infix operator => {}
func =><In, Out>(a: In, b: In -> Out) -> Out {
  return try b(a)
}

infix operator ?=> {}
func ?=><In, Out>(a: In?, b: In -> Out?) -> Out? {
  if let unwrapped = a {
      return try b(a)
  }
  return nil
}

//some defined functions

func defaultDestination() -> (x: Int, y: Int)
func loadedDestination() -> (x: Int, y: Int)?
func moveTo(x: Int, y: Int)

//actual code

defaultDestination() => moveTo
loadedDestination() ?=> moveTo ?? print("load failed")

//code without functional chaining

let point = defaultDestination()
moveTo(x: point.x, y: point.y)

if let loaded = loadedDestination() {
  moveTo(x: loaded.x, y: loaded.y)
} else {
  print("load failed")
}

I'm expecting this to stop working at some point in Swift 3's development, since it is related to tuple splat. I've heard talk of tuple splat returning in the future through an operator, with the stand-in syntax:

moveTo(*defaultDestination())

So, how would a functional chaining operator work under these conditions? It would require a second variadic splat operator:

defaultDestination() => *moveTo(x:y:)

The motivation for removing the standard form of tuple splat is that the calling syntax looks like an overload. But in this case, an explicit splat operator doesn't add any clarity, since the function being referred to can be unambiguous.

So, my question is whether this is worth removing full support for in the first place. This behaviour can be make to fit Swift 3's distinction of parameter lists and tuples, by applying specific rules to the existing behaviour to create a lightweight variadics system:

takesAClosure<T>(_: (T) -> ()) //closure explicitly takes a single parameter

takesAClosure<T>(_: T -> ()) //closure takes any number of parameters

takesAClosure<T>(_: T, _: T -> ()) //closure takes any number of parameters, but must have a parameter list which can be directly represented as a tuple

Either way, I'm hoping whatever syntax ends up chosen for variadics is nearly as simple to use as tuple splat has been, tuples are (literally) made for this purpose. I'll be disappointed to see this feature removed.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(James Froggatt) #6

Thanks for pointing out the warning, I wouldn't have known otherwise. I tested using ‘try’ on a non-throwing function in the iOS Swift Playgrounds app, and didn't get a warning. The app doesn't seem to give warnings, only errors.

Relatedly, I think bracketless T -> T should be an error, not a warning, in Swift 3.

Int -> Int //returns the same type
(Int) -> Int //returns… yes, it is the same type, it's just stating the obvious

Especially if we're removing argument labels from function types, this just seems so redundant. I'm not sure I can bring myself to hurt the readability of my code just to silence pointless compiler warnings. :stuck_out_tongue:

Int, Int -> (Int, Int) //multiple parameters, not equivalent to the return type
(Int, Int) -> (Int, Int) //this function can be called with its tuple return type (I wish)

From James F

···

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

Thanks. I agree, a standard library operator would clearly be the preferred way to do this, at least for general use. Basing it upon the ‘as’ cast just means we don't have to have to deal with another magical operator (looking at the inability to overload ‘!’ and ‘?’), as well as easing the transition from Swift 2.

From James F

On 1 Jul 2016, at 22:11, Vladimir.S <svabox@gmail.com> wrote:

On 01.07.2016 23:55, James Froggatt wrote:
Thanks for the response. I understand function overloading is possible, but it isn't nearly as convinient.

Yes, agree.

However, if explicit conversion is the way forward, then in the spirit of keeping backwards-compatibility in some form, we could simply allow this:

let paramsClosure: (Int, Int) -> () = …
let tupleClosure = paramsClosure as ((Int, Int)) -> ()

The ‘as’ operator is already used for various type system magic (like converting T to Optional<T>), so this seems fairly natural. There shouldn't be any ambiguity, since overloads taking tuples would have either different labels or type signature:

Personally I also think that we need such `as` conversions from one to another. At least because IMO there is a lot of code that already use the feature of tuple splatting.

moveTo(x: Int, y: Int)
moveTo(_: (x: Int, y: Int)) //sneaky
moveTo(x: (x: Int, y: Int), y: Int) //plain dumb

let a = moveTo(x:y:)
let b = moveTo(_:slight_smile:
let c = moveTo(x:y:) as ((x: Int, y: Int), Int) -> () //cast needed, same as for any type-based overload

let d = moveTo(x:y:) as ((Int, Int)) -> () //unambiguously the first function

Since this is clearly an explicit cast, which doesn't fall under the ‘remove implicit tuple splat’ proposal, can we explicity decide to keep this?

A splat operator would then be user-definable (meaning fewer magic operators), just being applied to the function rather than the arguments:

moveTo(x: point.x, y: point.y)

(moveTo*)(point)

So, rather than a language addition, or even a modification of an existing proposal, this is something which sensibly should still be allowed even once ‘implicit tuple splat’ is removed. We'd actually be losing a decent feature if we remove this completely, as is acknowledged by the suggestion of an explicit splat operator in the proposal.

From James F

Actually I also see a solution in having both: explicit 'as' conversion and in special operator. I feel like such special operator could be important for functional programming in Swift. 'as' conversion is very verbose and you have to write it for each function again and again(or use typealias), but operator will use one compiler magic for all functions.

I believe core team should decide if they want to keep/allow such 'as' conversion in case the proposal will be accepted.

PS: Actually, I'm surprised your code compiles, since I removed the ‘rethrows’ decoration from the operator's function signature for brevity, but left the ‘try’ in the implementation itself. Does Swift promote non-throwing functions to throwing ones like that? I have to double-check I don't have stray ‘try’s lying around.

:slight_smile: Yes, I also was surprised with just warnings in these places, but not errors. Don't know if it is a bug or not. Can someone explain ?

Hint: check compilation warnings for your code.

On 1 Jul 2016, at 19:15, Vladimir.S <svabox@gmail.com> wrote:

Yes, I expect that with the implemented proposal SE-0110 your code will not compile because `moveTo` has type `(Int, Int)->Void` and not required `((Int, Int))->Void`. You'll need to change the moveTo to accept tuple argument or use some function/operator to transform argument list parametrized function to function with tuple argument.

For example (this compiles now and IMO should after SE-0110 implemented, if accepted):

//function application operator
infix operator => {}
func =><In, Out>(a: In, b: (In) -> Out) -> Out {
return try b(a)
}

infix operator ?=> {}
func ?=><In, Out>(a: In?, b: (In) -> Out?) -> Out? {
if let unwrapped = a {
     return try b(unwrapped)
}
return nil
}

//some defined functions

func defaultDestination() -> (x: Int, y: Int) {return (1,1) }
func loadedDestination() -> (x: Int, y: Int)? {return nil }

// ---- Variant 1 ----
func moveTo1(point: (x: Int, y: Int)) {print("move1 to: ", point.x, point.y)}

// ---- Variant 2 ----
func moveTo2(x: Int, y: Int) {print("move2 to: ", x, y)}

func tupleize<T,U,V>(_ f: (T,U)->V ) -> ( ((T, U))->V ) {
return { tu in return f(tu.0, tu.1) }
}

//actual code

defaultDestination() => moveTo1
(loadedDestination() ?=> moveTo1) ?? print("load1 failed")

defaultDestination() => tupleize(moveTo2)
(loadedDestination() ?=> tupleize(moveTo2)) ?? print("load2 failed")

If we'll have such `tupleize` as built-in operator, then things will be even better. Don't see any problem here just like you, for example, don't expect function of (Int, (Int, String))->() will be accepted where (Int, Int, String)->() is required an so on. List of function arguments is not tuple at these days and so IMO only explicit conversion can exist to accept second when first is required and vice-versa. But I'm storng +1 to have such handy convertion operator.

On 01.07.2016 17:16, James Froggatt via swift-evolution wrote:
Currently, the following code is allowed:

//function application operator
infix operator => {}
func =><In, Out>(a: In, b: In -> Out) -> Out {
return try b(a)
}

infix operator ?=> {}
func ?=><In, Out>(a: In?, b: In -> Out?) -> Out? {
if let unwrapped = a {
     return try b(a)
}
return nil
}

//some defined functions

func defaultDestination() -> (x: Int, y: Int)
func loadedDestination() -> (x: Int, y: Int)?
func moveTo(x: Int, y: Int)

//actual code

defaultDestination() => moveTo
loadedDestination() ?=> moveTo ?? print("load failed")

//code without functional chaining

let point = defaultDestination()
moveTo(x: point.x, y: point.y)

if let loaded = loadedDestination() {
moveTo(x: loaded.x, y: loaded.y)
} else {
print("load failed")
}

I'm expecting this to stop working at some point in Swift 3's development, since it is related to tuple splat. I've heard talk of tuple splat returning in the future through an operator, with the stand-in syntax:

moveTo(*defaultDestination())

So, how would a functional chaining operator work under these conditions? It would require a second variadic splat operator:

defaultDestination() => *moveTo(x:y:)

The motivation for removing the standard form of tuple splat is that the calling syntax looks like an overload. But in this case, an explicit splat operator doesn't add any clarity, since the function being referred to can be unambiguous.

So, my question is whether this is worth removing full support for in the first place. This behaviour can be make to fit Swift 3's distinction of parameter lists and tuples, by applying specific rules to the existing behaviour to create a lightweight variadics system:

takesAClosure<T>(_: (T) -> ()) //closure explicitly takes a single parameter

takesAClosure<T>(_: T -> ()) //closure takes any number of parameters

takesAClosure<T>(_: T, _: T -> ()) //closure takes any number of parameters, but must have a parameter list which can be directly represented as a tuple

Either way, I'm hoping whatever syntax ends up chosen for variadics is nearly as simple to use as tuple splat has been, tuples are (literally) made for this purpose. I'll be disappointed to see this feature removed.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Vladimir) #7

Thanks for pointing out the warning, I wouldn't have known otherwise. I tested using �etry�f on a non-throwing function in the iOS Swift Playgrounds app, and didn't get a warning. The app doesn't seem to give warnings, only errors.

Relatedly, I think bracketless T -> T should be an error, not a warning, in Swift 3.

Strange, I also thought the proposal was to disallow such syntax, not just produce warnings. May be the work is in progress still..

···

On 02.07.2016 0:42, James Froggatt wrote:

Int -> Int //returns the same type
(Int) -> Int //returns�c yes, it is the same type, it's just stating the obvious

Especially if we're removing argument labels from function types, this just seems so redundant. I'm not sure I can bring myself to hurt the readability of my code just to silence pointless compiler warnings. :stuck_out_tongue:

Int, Int -> (Int, Int) //multiple parameters, not equivalent to the return type
(Int, Int) -> (Int, Int) //this function can be called with its tuple return type (I wish)

From James F

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

Thanks. I agree, a standard library operator would clearly be the preferred way to do this, at least for general use. Basing it upon the �eas�f cast just means we don't have to have to deal with another magical operator (looking at the inability to overload �e!�f and �e?�f), as well as easing the transition from Swift 2.

From James F

On 1 Jul 2016, at 22:11, Vladimir.S <svabox@gmail.com> wrote:

On 01.07.2016 23:55, James Froggatt wrote:
Thanks for the response. I understand function overloading is possible, but it isn't nearly as convinient.

Yes, agree.

However, if explicit conversion is the way forward, then in the spirit of keeping backwards-compatibility in some form, we could simply allow this:

let paramsClosure: (Int, Int) -> () = �c
let tupleClosure = paramsClosure as ((Int, Int)) -> ()

The �eas�f operator is already used for various type system magic (like converting T to Optional<T>), so this seems fairly natural. There shouldn't be any ambiguity, since overloads taking tuples would have either different labels or type signature:

Personally I also think that we need such `as` conversions from one to another. At least because IMO there is a lot of code that already use the feature of tuple splatting.

moveTo(x: Int, y: Int)
moveTo(_: (x: Int, y: Int)) //sneaky
moveTo(x: (x: Int, y: Int), y: Int) //plain dumb

let a = moveTo(x:y:)
let b = moveTo(_:slight_smile:
let c = moveTo(x:y:) as ((x: Int, y: Int), Int) -> () //cast needed, same as for any type-based overload

let d = moveTo(x:y:) as ((Int, Int)) -> () //unambiguously the first function

Since this is clearly an explicit cast, which doesn't fall under the �eremove implicit tuple splat�f proposal, can we explicity decide to keep this?

A splat operator would then be user-definable (meaning fewer magic operators), just being applied to the function rather than the arguments:

moveTo(x: point.x, y: point.y)

(moveTo*)(point)

So, rather than a language addition, or even a modification of an existing proposal, this is something which sensibly should still be allowed even once �eimplicit tuple splat�f is removed. We'd actually be losing a decent feature if we remove this completely, as is acknowledged by the suggestion of an explicit splat operator in the proposal.

From James F

Actually I also see a solution in having both: explicit 'as' conversion and in special operator. I feel like such special operator could be important for functional programming in Swift. 'as' conversion is very verbose and you have to write it for each function again and again(or use typealias), but operator will use one compiler magic for all functions.

I believe core team should decide if they want to keep/allow such 'as' conversion in case the proposal will be accepted.

PS: Actually, I'm surprised your code compiles, since I removed the �erethrows�f decoration from the operator's function signature for brevity, but left the �etry�f in the implementation itself. Does Swift promote non-throwing functions to throwing ones like that? I have to double-check I don't have stray �etry�fs lying around.

:slight_smile: Yes, I also was surprised with just warnings in these places, but not errors. Don't know if it is a bug or not. Can someone explain ?

Hint: check compilation warnings for your code.

On 1 Jul 2016, at 19:15, Vladimir.S <svabox@gmail.com> wrote:

Yes, I expect that with the implemented proposal SE-0110 your code will not compile because `moveTo` has type `(Int, Int)->Void` and not required `((Int, Int))->Void`. You'll need to change the moveTo to accept tuple argument or use some function/operator to transform argument list parametrized function to function with tuple argument.

For example (this compiles now and IMO should after SE-0110 implemented, if accepted):

//function application operator
infix operator => {}
func =><In, Out>(a: In, b: (In) -> Out) -> Out {
return try b(a)
}

infix operator ?=> {}
func ?=><In, Out>(a: In?, b: (In) -> Out?) -> Out? {
if let unwrapped = a {
     return try b(unwrapped)
}
return nil
}

//some defined functions

func defaultDestination() -> (x: Int, y: Int) {return (1,1) }
func loadedDestination() -> (x: Int, y: Int)? {return nil }

// ---- Variant 1 ----
func moveTo1(point: (x: Int, y: Int)) {print("move1 to: ", point.x, point.y)}

// ---- Variant 2 ----
func moveTo2(x: Int, y: Int) {print("move2 to: ", x, y)}

func tupleize<T,U,V>(_ f: (T,U)->V ) -> ( ((T, U))->V ) {
return { tu in return f(tu.0, tu.1) }
}

//actual code

defaultDestination() => moveTo1
(loadedDestination() ?=> moveTo1) ?? print("load1 failed")

defaultDestination() => tupleize(moveTo2)
(loadedDestination() ?=> tupleize(moveTo2)) ?? print("load2 failed")

If we'll have such `tupleize` as built-in operator, then things will be even better. Don't see any problem here just like you, for example, don't expect function of (Int, (Int, String))->() will be accepted where (Int, Int, String)->() is required an so on. List of function arguments is not tuple at these days and so IMO only explicit conversion can exist to accept second when first is required and vice-versa. But I'm storng +1 to have such handy convertion operator.

On 01.07.2016 17:16, James Froggatt via swift-evolution wrote:
Currently, the following code is allowed:

//function application operator
infix operator => {}
func =><In, Out>(a: In, b: In -> Out) -> Out {
return try b(a)
}

infix operator ?=> {}
func ?=><In, Out>(a: In?, b: In -> Out?) -> Out? {
if let unwrapped = a {
     return try b(a)
}
return nil
}

//some defined functions

func defaultDestination() -> (x: Int, y: Int)
func loadedDestination() -> (x: Int, y: Int)?
func moveTo(x: Int, y: Int)

//actual code

defaultDestination() => moveTo
loadedDestination() ?=> moveTo ?? print("load failed")

//code without functional chaining

let point = defaultDestination()
moveTo(x: point.x, y: point.y)

if let loaded = loadedDestination() {
moveTo(x: loaded.x, y: loaded.y)
} else {
print("load failed")
}

I'm expecting this to stop working at some point in Swift 3's development, since it is related to tuple splat. I've heard talk of tuple splat returning in the future through an operator, with the stand-in syntax:

moveTo(*defaultDestination())

So, how would a functional chaining operator work under these conditions? It would require a second variadic splat operator:

defaultDestination() => *moveTo(x:y:)

The motivation for removing the standard form of tuple splat is that the calling syntax looks like an overload. But in this case, an explicit splat operator doesn't add any clarity, since the function being referred to can be unambiguous.

So, my question is whether this is worth removing full support for in the first place. This behaviour can be make to fit Swift 3's distinction of parameter lists and tuples, by applying specific rules to the existing behaviour to create a lightweight variadics system:

takesAClosure<T>(_: (T) -> ()) //closure explicitly takes a single parameter

takesAClosure<T>(_: T -> ()) //closure takes any number of parameters

takesAClosure<T>(_: T, _: T -> ()) //closure takes any number of parameters, but must have a parameter list which can be directly represented as a tuple

Either way, I'm hoping whatever syntax ends up chosen for variadics is nearly as simple to use as tuple splat has been, tuples are (literally) made for this purpose. I'll be disappointed to see this feature removed.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(James Froggatt) #8

So what's the official stance on this?

Is SE0029 specifically prohibiting the use of tuple splat as pure syntactic sugar?
Or does it extend to…

Tuple splat in generic contexts:

function<A, B>(a: A, b: (A) -> B) -> B {
    b(a)
}
function(a: tupleValue, b: splattableFunction)

Explicit casts, of the form:

let closure: (A, B) -> ()
let explicitSplatted = closure as ((A, B)) -> ()

In addition, with the explicit parameter list for function types requirement, variadic generic functions become unambiguous:

function<A, B>(a: A, b: A -> B) { //the parameter list is the generic type
    b(a)
}

//implying this should be possible
function(a: (&self.local, aConstant), b: aFunction)

It's worth considering under the old/current syntax, A -> B implicitly allows variadic parameter lists (splatting the parameter list internally, since parameter lists don't have a better type-system model).
If we are to remove this feature, it is a breaking change, severely so to functional libraries and their users, which ought to get its own proposal.
If we are to fix this, parameter lists would be properly be modelled as a nonescaping tuple-like type, which would also require a proposal.
We could also just leave it as it is now, and introduce parameter lists or variadics to the type system in the future with minor changes to this particular case's syntax.

From James F

···

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

Thanks. I agree, a standard library operator would clearly be the preferred way to do this, at least for general use. Basing it upon the ‘as’ cast just means we don't have to have to deal with another magical operator (looking at the inability to overload ‘!’ and ‘?’), as well as easing the transition from Swift 2.

From James F

On 1 Jul 2016, at 22:11, Vladimir.S <svabox@gmail.com> wrote:

On 01.07.2016 23:55, James Froggatt wrote:
Thanks for the response. I understand function overloading is possible, but it isn't nearly as convinient.

Yes, agree.

However, if explicit conversion is the way forward, then in the spirit of keeping backwards-compatibility in some form, we could simply allow this:

let paramsClosure: (Int, Int) -> () = …
let tupleClosure = paramsClosure as ((Int, Int)) -> ()

The ‘as’ operator is already used for various type system magic (like converting T to Optional<T>), so this seems fairly natural. There shouldn't be any ambiguity, since overloads taking tuples would have either different labels or type signature:

Personally I also think that we need such `as` conversions from one to another. At least because IMO there is a lot of code that already use the feature of tuple splatting.

moveTo(x: Int, y: Int)
moveTo(_: (x: Int, y: Int)) //sneaky
moveTo(x: (x: Int, y: Int), y: Int) //plain dumb

let a = moveTo(x:y:)
let b = moveTo(_:slight_smile:
let c = moveTo(x:y:) as ((x: Int, y: Int), Int) -> () //cast needed, same as for any type-based overload

let d = moveTo(x:y:) as ((Int, Int)) -> () //unambiguously the first function

Since this is clearly an explicit cast, which doesn't fall under the ‘remove implicit tuple splat’ proposal, can we explicity decide to keep this?

A splat operator would then be user-definable (meaning fewer magic operators), just being applied to the function rather than the arguments:

moveTo(x: point.x, y: point.y)

(moveTo*)(point)

So, rather than a language addition, or even a modification of an existing proposal, this is something which sensibly should still be allowed even once ‘implicit tuple splat’ is removed. We'd actually be losing a decent feature if we remove this completely, as is acknowledged by the suggestion of an explicit splat operator in the proposal.

From James F

Actually I also see a solution in having both: explicit 'as' conversion and in special operator. I feel like such special operator could be important for functional programming in Swift. 'as' conversion is very verbose and you have to write it for each function again and again(or use typealias), but operator will use one compiler magic for all functions.

I believe core team should decide if they want to keep/allow such 'as' conversion in case the proposal will be accepted.

PS: Actually, I'm surprised your code compiles, since I removed the ‘rethrows’ decoration from the operator's function signature for brevity, but left the ‘try’ in the implementation itself. Does Swift promote non-throwing functions to throwing ones like that? I have to double-check I don't have stray ‘try’s lying around.

:slight_smile: Yes, I also was surprised with just warnings in these places, but not errors. Don't know if it is a bug or not. Can someone explain ?

Hint: check compilation warnings for your code.

On 1 Jul 2016, at 19:15, Vladimir.S <svabox@gmail.com> wrote:

Yes, I expect that with the implemented proposal SE-0110 your code will not compile because `moveTo` has type `(Int, Int)->Void` and not required `((Int, Int))->Void`. You'll need to change the moveTo to accept tuple argument or use some function/operator to transform argument list parametrized function to function with tuple argument.

For example (this compiles now and IMO should after SE-0110 implemented, if accepted):

//function application operator
infix operator => {}
func =><In, Out>(a: In, b: (In) -> Out) -> Out {
return try b(a)
}

infix operator ?=> {}
func ?=><In, Out>(a: In?, b: (In) -> Out?) -> Out? {
if let unwrapped = a {
     return try b(unwrapped)
}
return nil
}

//some defined functions

func defaultDestination() -> (x: Int, y: Int) {return (1,1) }
func loadedDestination() -> (x: Int, y: Int)? {return nil }

// ---- Variant 1 ----
func moveTo1(point: (x: Int, y: Int)) {print("move1 to: ", point.x, point.y)}

// ---- Variant 2 ----
func moveTo2(x: Int, y: Int) {print("move2 to: ", x, y)}

func tupleize<T,U,V>(_ f: (T,U)->V ) -> ( ((T, U))->V ) {
return { tu in return f(tu.0, tu.1) }
}

//actual code

defaultDestination() => moveTo1
(loadedDestination() ?=> moveTo1) ?? print("load1 failed")

defaultDestination() => tupleize(moveTo2)
(loadedDestination() ?=> tupleize(moveTo2)) ?? print("load2 failed")

If we'll have such `tupleize` as built-in operator, then things will be even better. Don't see any problem here just like you, for example, don't expect function of (Int, (Int, String))->() will be accepted where (Int, Int, String)->() is required an so on. List of function arguments is not tuple at these days and so IMO only explicit conversion can exist to accept second when first is required and vice-versa. But I'm storng +1 to have such handy convertion operator.

On 01.07.2016 17:16, James Froggatt via swift-evolution wrote:
Currently, the following code is allowed:

//function application operator
infix operator => {}
func =><In, Out>(a: In, b: In -> Out) -> Out {
return try b(a)
}

infix operator ?=> {}
func ?=><In, Out>(a: In?, b: In -> Out?) -> Out? {
if let unwrapped = a {
     return try b(a)
}
return nil
}

//some defined functions

func defaultDestination() -> (x: Int, y: Int)
func loadedDestination() -> (x: Int, y: Int)?
func moveTo(x: Int, y: Int)

//actual code

defaultDestination() => moveTo
loadedDestination() ?=> moveTo ?? print("load failed")

//code without functional chaining

let point = defaultDestination()
moveTo(x: point.x, y: point.y)

if let loaded = loadedDestination() {
moveTo(x: loaded.x, y: loaded.y)
} else {
print("load failed")
}

I'm expecting this to stop working at some point in Swift 3's development, since it is related to tuple splat. I've heard talk of tuple splat returning in the future through an operator, with the stand-in syntax:

moveTo(*defaultDestination())

So, how would a functional chaining operator work under these conditions? It would require a second variadic splat operator:

defaultDestination() => *moveTo(x:y:)

The motivation for removing the standard form of tuple splat is that the calling syntax looks like an overload. But in this case, an explicit splat operator doesn't add any clarity, since the function being referred to can be unambiguous.

So, my question is whether this is worth removing full support for in the first place. This behaviour can be make to fit Swift 3's distinction of parameter lists and tuples, by applying specific rules to the existing behaviour to create a lightweight variadics system:

takesAClosure<T>(_: (T) -> ()) //closure explicitly takes a single parameter

takesAClosure<T>(_: T -> ()) //closure takes any number of parameters

takesAClosure<T>(_: T, _: T -> ()) //closure takes any number of parameters, but must have a parameter list which can be directly represented as a tuple

Either way, I'm hoping whatever syntax ends up chosen for variadics is nearly as simple to use as tuple splat has been, tuples are (literally) made for this purpose. I'll be disappointed to see this feature removed.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Chris Lattner) #9

Correct, it should be an error, but is staged in as a warning.

-Chris

···

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

On 02.07.2016 0:42, James Froggatt wrote:

Thanks for pointing out the warning, I wouldn't have known otherwise. I tested using ‘try’ on a non-throwing function in the iOS Swift Playgrounds app, and didn't get a warning. The app doesn't seem to give warnings, only errors.

Relatedly, I think bracketless T -> T should be an error, not a warning, in Swift 3.

Strange, I also thought the proposal was to disallow such syntax, not just produce warnings. May be the work is in progress still..