Should closures support inout parameters?


(Braeden Profile) #1

I was writing some code that would allow transformations of values as part of an expression, and I came across a strange error:

/// Returns the operand after a given transformation.
///
/// Example: `let newRect = myRect << { $0.origin.x += 3 }`
func << <T> (given: T, transformation: (inout T) -> ()) -> T
{
  var result = given
  transformation(&result)
  return result
}

let volume = component.volume << { $0.ranges.z.width = 0 } // Error: Expression type () is ambiguous without more context.
let volume = component.volume << { $0.ranges.z.width = 0; return () } // Error: Cannot assign to property: ‘$0’ is immutable.
let volume = component.volume << { (x: inout SCNBoxVolume) in x.ranges.z.width = 0 } // Succeeds!

Obviously, this code could easily create a var for volume and mutate it, but it doesn’t solve my problem. Am I misunderstanding how this could work? This is the only overload of << that accepts a closure, and even the code completion recognizes that $0 is a SCNBoxVolume. It’s just strange that the compiler won’t recognize $0 as an inout parameter off the bat.

Is this a bug, or a design choice?


(Dave Abrahams) #2

I was writing some code that would allow transformations of values as
part of an expression, and I came across a strange error:

/// Returns the operand after a given transformation.
///
/// Example: `let newRect = myRect << { $0.origin.x += 3 }`
func << <T> (given: T, transformation: (inout T) -> ()) -> T
{
  var result = given
  transformation(&result)
  return result
}

let volume = component.volume << { $0.ranges.z.width = 0 } // Error:
Expression type () is ambiguous without more context.
let volume = component.volume << { $0.ranges.z.width = 0; return () }
// Error: Cannot assign to property: ‘$0’ is immutable.
let volume = component.volume << { (x: inout SCNBoxVolume) in x.ranges.z.width = 0 } // Succeeds!

Obviously, this code could easily create a var for volume and mutate
it, but it doesn’t solve my problem. Am I misunderstanding how this
could work? This is the only overload of << that accepts a closure,
and even the code completion recognizes that $0 is a SCNBoxVolume.
It’s just strange that the compiler won’t recognize $0 as an inout
parameter off the bat.

I think the subject you wanted was “should we deduce closure inout
parameters?”

Is this a bug, or a design choice?

I've been wondering the same. I hope it's a bug, and I suggest you file
it.

···

on Fri Sep 16 2016, Braeden Profile <swift-evolution@swift.org> wrote:

--
-Dave


(Chris Lattner) #3

It’s a bug, it has been filed several times, it is pretty well known at this point.

-Chris

···

On Sep 18, 2016, at 8:17 AM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:

on Fri Sep 16 2016, Braeden Profile <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I was writing some code that would allow transformations of values as
part of an expression, and I came across a strange error:

/// Returns the operand after a given transformation.
///
/// Example: `let newRect = myRect << { $0.origin.x += 3 }`
func << <T> (given: T, transformation: (inout T) -> ()) -> T
{
  var result = given
  transformation(&result)
  return result
}

let volume = component.volume << { $0.ranges.z.width = 0 } // Error:
Expression type () is ambiguous without more context.
let volume = component.volume << { $0.ranges.z.width = 0; return () }
// Error: Cannot assign to property: ‘$0’ is immutable.
let volume = component.volume << { (x: inout SCNBoxVolume) in x.ranges.z.width = 0 } // Succeeds!

Obviously, this code could easily create a var for volume and mutate
it, but it doesn’t solve my problem. Am I misunderstanding how this
could work? This is the only overload of << that accepts a closure,
and even the code completion recognizes that $0 is a SCNBoxVolume.
It’s just strange that the compiler won’t recognize $0 as an inout
parameter off the bat.

I think the subject you wanted was “should we deduce closure inout
parameters?”

Is this a bug, or a design choice?

I've been wondering the same. I hope it's a bug, and I suggest you file
it.


(Goffredo Marocchi) #4

Good :), will it get put with the next Swift revision then?

···

Sent from my iPhone

On 19 Sep 2016, at 08:37, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

On Sep 18, 2016, at 8:17 AM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:

on Fri Sep 16 2016, Braeden Profile <swift-evolution@swift.org> wrote:

I was writing some code that would allow transformations of values as
part of an expression, and I came across a strange error:

/// Returns the operand after a given transformation.
///
/// Example: `let newRect = myRect << { $0.origin.x += 3 }`
func << <T> (given: T, transformation: (inout T) -> ()) -> T
{
  var result = given
  transformation(&result)
  return result
}

let volume = component.volume << { $0.ranges.z.width = 0 } // Error:
Expression type () is ambiguous without more context.
let volume = component.volume << { $0.ranges.z.width = 0; return () }
// Error: Cannot assign to property: ‘$0’ is immutable.
let volume = component.volume << { (x: inout SCNBoxVolume) in x.ranges.z.width = 0 } // Succeeds!

Obviously, this code could easily create a var for volume and mutate
it, but it doesn’t solve my problem. Am I misunderstanding how this
could work? This is the only overload of << that accepts a closure,
and even the code completion recognizes that $0 is a SCNBoxVolume.
It’s just strange that the compiler won’t recognize $0 as an inout
parameter off the bat.

I think the subject you wanted was “should we deduce closure inout
parameters?”

Is this a bug, or a design choice?

I've been wondering the same. I hope it's a bug, and I suggest you file
it.

It’s a bug, it has been filed several times, it is pretty well known at this point.

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