Proposal: Keep var on Function Parameters and Pattern Matching


(Francisco Costa) #1

Hello all,

There is currently a proposal to remove `var` from Function Parameters and
Pattern Matching which seems to have been already accepted

https://github.com/apple/swift-evolution/blob/master/proposals/0003-remove-var-parameters-patterns.md

I cannot find the discussion on it, probably because it predates the open
sourcing of Swift. While some of its arguments may sound reasonable, I
think they have been greatly exaggerated.

The main point of the proposal seems to be that the `var` attribute can be
easily confused with `inout`. It then provides examples where `var` would
be completely useless:

func foo(i: Int) {
  i += 1 // Illegal
}

func foo(var i: Int) {
  i += 1 // Legal but useless since we are not using this local value
anywhere
}

We today made a quick survey around the backend developers on the office
(not familiar with Swift) and not a single one suggested that the second
method would mutate the original parameter value. In fact, to all of them
it was clear that `var` creates a local copy of the value and that the
method is also missing a `return` if we want to use the incremented value.

The Swift Language Guide gives a good explanation on this as well:

"Variable parameters ... give a new modifiable copy of the parameter’s
value for your function to work with."

This is probably a concept most beginners to the language can either guess
intuitively or learn in a couple of seconds.

Especially taking into account that the way we use `inout` parameters is so
much advertised in Swift, to the point where calling a method with them
requires to explicitly identify them with `&`, it seems that by giving up
the `var` attribute we would lose a convenient elegance in exchange for no
real benefit to beginners.

In fact, in my experience the `var` attribute is most often used in
scenarios where immutability is intentionally preserved, we pass a
immutable value to a method and it returns another immutable (modified)
version of that value.

Another common scenario is when you need to further modify a value that was
unwrapped from an Optional. I would argue that this seems elegant and easy
to read:

if var x = getOptionalInt() {
  x += 1
  return x
}

While this (as has been proposed) seems like we are fighting a language
limitation:

if let x = getOptionalInt() {
  var x = x
  x += 1
  return x
}

I understand that discussing back and forth proposals that have been
already accepted is counter-productive, but since this discussion doesn't
seem to have been published, I would kindly ask if we can give it a second
thought :slight_smile:

Thanks,
Francisco


(Step C) #2

While we were discussing this proposal, a team member objected saying he
had fixed a bug related to using `var` this summer. It turned out he had
actually fixed the bug by switching to `inout` _from_ `var`. This is an
experienced dev with plenty of resources and Swift knowledge.

So yes, it is not only possible but has definitely happened that this
confusion exists for some developers. We were surprised but group
conclusion was it validated the proposal. I was ambivalent on the proposal
initially, but overall I think it is the right direction for Swift.

Step Christopher
Big Nerd Ranch, LLC
schristopher@bignerdranch.com

···

On Tue, Dec 15, 2015 at 5:27 PM, Francisco Costa via swift-evolution < swift-evolution@swift.org> wrote:

Hello all,

There is currently a proposal to remove `var` from Function Parameters and
Pattern Matching which seems to have been already accepted

https://github.com/apple/swift-evolution/blob/master/proposals/0003-remove-var-parameters-patterns.md

I cannot find the discussion on it, probably because it predates the open
sourcing of Swift. While some of its arguments may sound reasonable, I
think they have been greatly exaggerated.

The main point of the proposal seems to be that the `var` attribute can be
easily confused with `inout`. It then provides examples where `var` would
be completely useless:

func foo(i: Int) {
  i += 1 // Illegal
}

func foo(var i: Int) {
  i += 1 // Legal but useless since we are not using this local value
anywhere
}

We today made a quick survey around the backend developers on the office
(not familiar with Swift) and not a single one suggested that the second
method would mutate the original parameter value. In fact, to all of them
it was clear that `var` creates a local copy of the value and that the
method is also missing a `return` if we want to use the incremented value.

The Swift Language Guide gives a good explanation on this as well:

"Variable parameters ... give a new modifiable copy of the parameter’s
value for your function to work with."

This is probably a concept most beginners to the language can either guess
intuitively or learn in a couple of seconds.

Especially taking into account that the way we use `inout` parameters is
so much advertised in Swift, to the point where calling a method with them
requires to explicitly identify them with `&`, it seems that by giving up
the `var` attribute we would lose a convenient elegance in exchange for no
real benefit to beginners.

In fact, in my experience the `var` attribute is most often used in
scenarios where immutability is intentionally preserved, we pass a
immutable value to a method and it returns another immutable (modified)
version of that value.

Another common scenario is when you need to further modify a value that
was unwrapped from an Optional. I would argue that this seems elegant and
easy to read:

if var x = getOptionalInt() {
  x += 1
  return x
}

While this (as has been proposed) seems like we are fighting a language
limitation:

if let x = getOptionalInt() {
  var x = x
  x += 1
  return x
}

I understand that discussing back and forth proposals that have been
already accepted is counter-productive, but since this discussion doesn't
seem to have been published, I would kindly ask if we can give it a second
thought :slight_smile:

Thanks,
Francisco

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


(Dennis Lysenko) #3

Francisco,

Can you run the same survey with an example that uses a struct called
"Song" instead? I think the confusion would lie in complex value types. Int
may be an unideal example.

···

On Tue, Dec 15, 2015, 5:27 PM Francisco Costa via swift-evolution < swift-evolution@swift.org> wrote:

Hello all,

There is currently a proposal to remove `var` from Function Parameters and
Pattern Matching which seems to have been already accepted

https://github.com/apple/swift-evolution/blob/master/proposals/0003-remove-var-parameters-patterns.md

I cannot find the discussion on it, probably because it predates the open
sourcing of Swift. While some of its arguments may sound reasonable, I
think they have been greatly exaggerated.

The main point of the proposal seems to be that the `var` attribute can be
easily confused with `inout`. It then provides examples where `var` would
be completely useless:

func foo(i: Int) {
  i += 1 // Illegal
}

func foo(var i: Int) {
  i += 1 // Legal but useless since we are not using this local value
anywhere
}

We today made a quick survey around the backend developers on the office
(not familiar with Swift) and not a single one suggested that the second
method would mutate the original parameter value. In fact, to all of them
it was clear that `var` creates a local copy of the value and that the
method is also missing a `return` if we want to use the incremented value.

The Swift Language Guide gives a good explanation on this as well:

"Variable parameters ... give a new modifiable copy of the parameter’s
value for your function to work with."

This is probably a concept most beginners to the language can either guess
intuitively or learn in a couple of seconds.

Especially taking into account that the way we use `inout` parameters is
so much advertised in Swift, to the point where calling a method with them
requires to explicitly identify them with `&`, it seems that by giving up
the `var` attribute we would lose a convenient elegance in exchange for no
real benefit to beginners.

In fact, in my experience the `var` attribute is most often used in
scenarios where immutability is intentionally preserved, we pass a
immutable value to a method and it returns another immutable (modified)
version of that value.

Another common scenario is when you need to further modify a value that
was unwrapped from an Optional. I would argue that this seems elegant and
easy to read:

if var x = getOptionalInt() {
  x += 1
  return x
}

While this (as has been proposed) seems like we are fighting a language
limitation:

if let x = getOptionalInt() {
  var x = x
  x += 1
  return x
}

I understand that discussing back and forth proposals that have been
already accepted is counter-productive, but since this discussion doesn't
seem to have been published, I would kindly ask if we can give it a second
thought :slight_smile:

Thanks,
Francisco

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


(Francisco Costa) #4

Thanks Stephen for the insight!

The way Swift prevents us from inadvertently writing common bugs is one of
the many things that makes it great, and I absolutely agree that this
confusion must be handled. However I would still prefer if this would be
less aggressively fixed with a warning telling us when a struct has been
copied but the new value has not been returned or used in the outer scope,
rather than removing the feature entirely. How hard it would be to
implement such a warning I am not sure though.

Francisco

···

On Wed, Dec 16, 2015 at 12:29 AM, Stephen Christopher < schristopher@bignerdranch.com> wrote:

While we were discussing this proposal, a team member objected saying he
had fixed a bug related to using `var` this summer. It turned out he had
actually fixed the bug by switching to `inout` _from_ `var`. This is an
experienced dev with plenty of resources and Swift knowledge.

So yes, it is not only possible but has definitely happened that this
confusion exists for some developers. We were surprised but group
conclusion was it validated the proposal. I was ambivalent on the proposal
initially, but overall I think it is the right direction for Swift.

Step Christopher
Big Nerd Ranch, LLC
schristopher@bignerdranch.com

On Tue, Dec 15, 2015 at 5:27 PM, Francisco Costa via swift-evolution < > swift-evolution@swift.org> wrote:

Hello all,

There is currently a proposal to remove `var` from Function Parameters
and Pattern Matching which seems to have been already accepted

https://github.com/apple/swift-evolution/blob/master/proposals/0003-remove-var-parameters-patterns.md

I cannot find the discussion on it, probably because it predates the open
sourcing of Swift. While some of its arguments may sound reasonable, I
think they have been greatly exaggerated.

The main point of the proposal seems to be that the `var` attribute can
be easily confused with `inout`. It then provides examples where `var`
would be completely useless:

func foo(i: Int) {
  i += 1 // Illegal
}

func foo(var i: Int) {
  i += 1 // Legal but useless since we are not using this local value
anywhere
}

We today made a quick survey around the backend developers on the office
(not familiar with Swift) and not a single one suggested that the second
method would mutate the original parameter value. In fact, to all of them
it was clear that `var` creates a local copy of the value and that the
method is also missing a `return` if we want to use the incremented value.

The Swift Language Guide gives a good explanation on this as well:

"Variable parameters ... give a new modifiable copy of the parameter’s
value for your function to work with."

This is probably a concept most beginners to the language can either
guess intuitively or learn in a couple of seconds.

Especially taking into account that the way we use `inout` parameters is
so much advertised in Swift, to the point where calling a method with them
requires to explicitly identify them with `&`, it seems that by giving up
the `var` attribute we would lose a convenient elegance in exchange for no
real benefit to beginners.

In fact, in my experience the `var` attribute is most often used in
scenarios where immutability is intentionally preserved, we pass a
immutable value to a method and it returns another immutable (modified)
version of that value.

Another common scenario is when you need to further modify a value that
was unwrapped from an Optional. I would argue that this seems elegant and
easy to read:

if var x = getOptionalInt() {
  x += 1
  return x
}

While this (as has been proposed) seems like we are fighting a language
limitation:

if let x = getOptionalInt() {
  var x = x
  x += 1
  return x
}

I understand that discussing back and forth proposals that have been
already accepted is counter-productive, but since this discussion doesn't
seem to have been published, I would kindly ask if we can give it a second
thought :slight_smile:

Thanks,
Francisco

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


(Fabian Ehrentraud) #5

While I think it's good to loose `var` for parameters, the different semantics for Structs and Classes can be confusing sometimes. It is not always obvious at caller site, whether you are passing a Struct or a Class instance, and therefore whether the call will alter the instance at caller site.

···

On 16.12.2015, at 03:33, Dennis Lysenko via swift-evolution <swift-evolution@swift.org<mailto:swift-evolution@swift.org>> wrote:

Francisco,

Can you run the same survey with an example that uses a struct called "Song" instead? I think the confusion would lie in complex value types. Int may be an unideal example.

On Tue, Dec 15, 2015, 5:27 PM Francisco Costa via swift-evolution <swift-evolution@swift.org<mailto:swift-evolution@swift.org>> wrote:
Hello all,

There is currently a proposal to remove `var` from Function Parameters and Pattern Matching which seems to have been already accepted

https://github.com/apple/swift-evolution/blob/master/proposals/0003-remove-var-parameters-patterns.md

I cannot find the discussion on it, probably because it predates the open sourcing of Swift. While some of its arguments may sound reasonable, I think they have been greatly exaggerated.

The main point of the proposal seems to be that the `var` attribute can be easily confused with `inout`. It then provides examples where `var` would be completely useless:

func foo(i: Int) {
  i += 1 // Illegal
}

func foo(var i: Int) {
  i += 1 // Legal but useless since we are not using this local value anywhere
}

We today made a quick survey around the backend developers on the office (not familiar with Swift) and not a single one suggested that the second method would mutate the original parameter value. In fact, to all of them it was clear that `var` creates a local copy of the value and that the method is also missing a `return` if we want to use the incremented value.

The Swift Language Guide gives a good explanation on this as well:

"Variable parameters ... give a new modifiable copy of the parameter’s value for your function to work with."

This is probably a concept most beginners to the language can either guess intuitively or learn in a couple of seconds.

Especially taking into account that the way we use `inout` parameters is so much advertised in Swift, to the point where calling a method with them requires to explicitly identify them with `&`, it seems that by giving up the `var` attribute we would lose a convenient elegance in exchange for no real benefit to beginners.

In fact, in my experience the `var` attribute is most often used in scenarios where immutability is intentionally preserved, we pass a immutable value to a method and it returns another immutable (modified) version of that value.

Another common scenario is when you need to further modify a value that was unwrapped from an Optional. I would argue that this seems elegant and easy to read:

if var x = getOptionalInt() {
  x += 1
  return x
}

While this (as has been proposed) seems like we are fighting a language limitation:

if let x = getOptionalInt() {
  var x = x
  x += 1
  return x
}

I understand that discussing back and forth proposals that have been already accepted is counter-productive, but since this discussion doesn't seem to have been published, I would kindly ask if we can give it a second thought :slight_smile:

Thanks,
Francisco

_______________________________________________
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


(Francisco Costa) #6

Thanks Dennis, you have a great point there! Int is intuitively thought to
be passed as a value in most languages.

Out of curiosity I made a quick poll based on your suggestion

https://twitter.com/phelgo/status/677047198824202241

Lets see what answers do we get

Francisco

···

On Wed, Dec 16, 2015 at 3:33 AM, Dennis Lysenko <dennis.s.lysenko@gmail.com> wrote:

Francisco,

Can you run the same survey with an example that uses a struct called
"Song" instead? I think the confusion would lie in complex value types. Int
may be an unideal example.

On Tue, Dec 15, 2015, 5:27 PM Francisco Costa via swift-evolution < > swift-evolution@swift.org> wrote:

Hello all,

There is currently a proposal to remove `var` from Function Parameters
and Pattern Matching which seems to have been already accepted

https://github.com/apple/swift-evolution/blob/master/proposals/0003-remove-var-parameters-patterns.md

I cannot find the discussion on it, probably because it predates the open
sourcing of Swift. While some of its arguments may sound reasonable, I
think they have been greatly exaggerated.

The main point of the proposal seems to be that the `var` attribute can
be easily confused with `inout`. It then provides examples where `var`
would be completely useless:

func foo(i: Int) {
  i += 1 // Illegal
}

func foo(var i: Int) {
  i += 1 // Legal but useless since we are not using this local value
anywhere
}

We today made a quick survey around the backend developers on the office
(not familiar with Swift) and not a single one suggested that the second
method would mutate the original parameter value. In fact, to all of them
it was clear that `var` creates a local copy of the value and that the
method is also missing a `return` if we want to use the incremented value.

The Swift Language Guide gives a good explanation on this as well:

"Variable parameters ... give a new modifiable copy of the parameter’s
value for your function to work with."

This is probably a concept most beginners to the language can either
guess intuitively or learn in a couple of seconds.

Especially taking into account that the way we use `inout` parameters is
so much advertised in Swift, to the point where calling a method with them
requires to explicitly identify them with `&`, it seems that by giving up
the `var` attribute we would lose a convenient elegance in exchange for no
real benefit to beginners.

In fact, in my experience the `var` attribute is most often used in
scenarios where immutability is intentionally preserved, we pass a
immutable value to a method and it returns another immutable (modified)
version of that value.

Another common scenario is when you need to further modify a value that
was unwrapped from an Optional. I would argue that this seems elegant and
easy to read:

if var x = getOptionalInt() {
  x += 1
  return x
}

While this (as has been proposed) seems like we are fighting a language
limitation:

if let x = getOptionalInt() {
  var x = x
  x += 1
  return x
}

I understand that discussing back and forth proposals that have been
already accepted is counter-productive, but since this discussion doesn't
seem to have been published, I would kindly ask if we can give it a second
thought :slight_smile:

Thanks,
Francisco

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