Skip to content

Revise SE-0003 for reconsideration of 'var' patterns #137

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 2, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ sampling of potentially good ideas that are not in scope for Swift

* [Better Translation of Objective-C APIs Into Swift](proposals/0005-objective-c-name-translation.md) (SE-0005)
* [Removing currying `func` declaration syntax](proposals/0002-remove-currying.md) (SE-0002)
* [Removing `var` from Function Parameters and Pattern Matching](proposals/0003-remove-var-parameters-patterns.md) (SE-0003)
* [Removing `var` from Function Parameters](proposals/0003-remove-var-parameters.md)
* [Remove the `++` and `--` operators](proposals/0004-remove-pre-post-inc-decrement.md) (SE-0004)
* [Remove C-style for-loops with conditions and incrementers](proposals/0007-remove-c-style-for-loops.md) (SE-0007)
* [Swift Testing](proposals/0019-package-manager-testing.md) (SE-0019)
Expand Down
225 changes: 0 additions & 225 deletions proposals/0003-remove-var-parameters-patterns.md

This file was deleted.

106 changes: 106 additions & 0 deletions proposals/0003-remove-var-parameters.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# Removing `var` from Function Parameters

* Proposal: [SE-0003](https://github.com/apple/swift-evolution/blob/master/proposals/0003-remove-var-parameters-patterns.md)
* Author(s): [David Farler](https://github.com/bitjammer)
* Status: **Accepted**
* Review manager: [Joe Pamer](https://github.com/jopamer)

## Note

This proposal underwent some major changes from its original form. See
the end of this document for historical information and why this
proposal changed.

## Introduction

There has been some confusion of semantics when a function parameter is
marked as `inout` compared to `var`. Both give a mutable local copy of a
value but parameters marked `inout` are automatically written back.

Function parameters are immutable by default:

```swift
func foo(i: Int) {
i += 1 // illegal
}

func foo(var i: Int) {
i += 1 // OK, but the caller cannot observe this mutation.
}
```

Here, the *local copy* of `x` mutates but the write does not propagate back to
the original value that was passed, so the caller can never observe the change
directly. For that to happen to value types, you have to mark the parameter
with `inout`:

```swift
func doSomethingWithInout(inout i: Int) {
i = 2 // This will have an effect on the caller's Int that was passed.
}

var x = 1
print(x) // 1

doSomethingWithVar(x)
print(x) // 1

doSomethingWithInout(&x)
print(x) // 2
```

## Motivation

Using `var` annotations on function parameters have limited utility,
optimizing for a line of code at the cost of confusion with `inout`,
which has the semantics most people expect. To emphasize the fact these
values are unique copies and don't have the write-back semantics of
`inout`, we should not allow `var` here.

In summary, the problems that motivate this change are:

- `var` is often confused with `inout` in function parameters.
- `var` is often confused to make value types have reference semantics.
- Function parameters are not refutable patterns like in *if-*,
*while-*, *guard-*, *for-in-*, and *case* statements.

## Design

This is a trivial change to the parser. In Swift 2.2, a deprecation
warning will be emitted while in Swift 3 it will become an error.

## Impact on existing code

As a purely mechanical migration away from these uses of `var`, a temporary
variable can be immediately introduced that shadows the immutable copy in all of
the above uses. For example:

```swift
func foo(i: Int) {
var i = i
}
```

However, shadowing is not necessarily an ideal fix and may indicate an
anti-pattern. We expect users of Swift to rethink some of their existing
code where these are used but it is not strictly necessary to react to
this language change.

## Alternatives considered

This proposal originally included removal of `var` bindings for all
refutable patterns as well as function parameters.

[Original SE-0003 Proposal](https://github.com/apple/swift-evolution/blob/8cd734260bc60d6d49dbfb48de5632e63bf200cc/proposals/0003-remove-var-parameters-patterns.md)

Removal of `var` from refutable patterns was reconsidered due to the
burden it placed on valid mutation patterns already in use in Swift 2
code. You can view the discussion on the swift-evolution mailing list
here:

[Initial Discussion of Reconsideration](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160118/007326.html)

The rationale for a final conclusion was also sent to the
swift-evolution list, which you can view here:

[Note on Revision of the Proposal](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160125/008145.html)