[Pitch] Replace 'inout' with '&'

For Swift 3, we're planning to phase out 'var' parameters in functions, and we're also making it so that language keywords are valid argument labels. With both of these changes pending, I have a hard time not reading:

func foo(inout x: Int)

as an argument labeled `inout` instead of an unlabeled argument bound to `x`. Once `var` is phased out, `inout` would also be the only remaining case where quoting is necessary to use a name as an argument label. The `inout` keyword has always struck me as weird, since it violates definition-follows-use—maybe we should replace it with the `&` sigil, mirroring its usage in call sites.

-Joe

-1

“inout” is intended to communicate (or at least hint at) the copy-in / copy-out behavior of the argument. It is also there to enable other parameter modifiers, which can enable other more advanced parameters models in the future (e.g. rust-style borrowing).

-Chris

···

On Dec 18, 2015, at 5:23 PM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

For Swift 3, we're planning to phase out 'var' parameters in functions, and we're also making it so that language keywords are valid argument labels. With both of these changes pending, I have a hard time not reading:

func foo(inout x: Int)

as an argument labeled `inout` instead of an unlabeled argument bound to `x`. Once `var` is phased out, `inout` would also be the only remaining case where quoting is necessary to use a name as an argument label. The `inout` keyword has always struck me as weird, since it violates definition-follows-use—maybe we should replace it with the `&` sigil, mirroring its usage in call sites.

I don't think this would be a problem in practice since it is hard for me
to imagine an API that would use 'inout' as a label -- at least they would
spell it 'inOut' according to our API guidelines (but I really think they
should call it something else).

There's also a possibility that we add 'out' parameters in the future, and
if 'inout' would be spelled '&', then we would need to find another sigil
for 'out'.

So, overall, I don't support this.

Dmitri

···

On Fri, Dec 18, 2015 at 5:23 PM, Joe Groff via swift-evolution < swift-evolution@swift.org> wrote:

For Swift 3, we're planning to phase out 'var' parameters in functions,
and we're also making it so that language keywords are valid argument
labels. With both of these changes pending, I have a hard time not reading:

func foo(inout x: Int)

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/

For Swift 3, we're planning to phase out 'var' parameters in functions, and we're also making it so that language keywords are valid argument labels. With both of these changes pending, I have a hard time not reading:

func foo(inout x: Int)

as an argument labeled `inout` instead of an unlabeled argument bound to `x`. Once `var` is phased out, `inout` would also be the only remaining case where quoting is necessary to use a name as an argument label. The `inout` keyword has always struck me as weird, since it violates definition-follows-use—maybe we should replace it with the `&` sigil, mirroring its usage in call sites.

<bikeshed>what about @inout?</bikeshed>

···

On Dec 18, 2015, at 5:23 PM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

-Joe

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

+1. Can you provide an example showing where you would place it though?

···

Sent from my iPad

On Dec 18, 2015, at 7:23 PM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

For Swift 3, we're planning to phase out 'var' parameters in functions, and we're also making it so that language keywords are valid argument labels. With both of these changes pending, I have a hard time not reading:

func foo(inout x: Int)

as an argument labeled `inout` instead of an unlabeled argument bound to `x`. Once `var` is phased out, `inout` would also be the only remaining case where quoting is necessary to use a name as an argument label. The `inout` keyword has always struck me as weird, since it violates definition-follows-use—maybe we should replace it with the `&` sigil, mirroring its usage in call sites.

-Joe

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

Good question. Three options I see:

- Before the label and binding names, where inout appears today, and where other argument modifiers like `@autoclosure` go: func foo(&label x: Int)

which is the minimal change.

- Before the binding name: func foo(label &x: Int)

which is problematic for implicitly-labeled arguments.

- Before the type name: func foo(label x: &Int)

This is the most definition-follows-use-y, but would be inconsistent with other argument modifiers.

-Joe

···

On Dec 18, 2015, at 5:27 PM, Matthew Johnson <matthew@anandabits.com> wrote:

+1. Can you provide an example showing where you would place it though?

What is your suggested term for these kinds of parameters once we retire “inout”?

-Dave

···

On Dec 18, 2015, at 5:30 PM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

On Dec 18, 2015, at 5:27 PM, Matthew Johnson <matthew@anandabits.com> wrote:

+1. Can you provide an example showing where you would place it though?

Good question. Three options I see:

- Before the label and binding names, where inout appears today, and where other argument modifiers like `@autoclosure` go: func foo(&label x: Int)

which is the minimal change.

- Before the binding name: func foo(label &x: Int)

which is problematic for implicitly-labeled arguments.

- Before the type name: func foo(label x: &Int)

This is the most definition-follows-use-y, but would be inconsistent with other argument modifiers.

I'd still call them 'inout', but I agree it's unfortunate that that wouldn't be spelled out anywhere in source.

-Joe

···

On Dec 18, 2015, at 5:33 PM, Dave Abrahams <dabrahams@apple.com> wrote:

On Dec 18, 2015, at 5:30 PM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

On Dec 18, 2015, at 5:27 PM, Matthew Johnson <matthew@anandabits.com> wrote:

+1. Can you provide an example showing where you would place it though?

Good question. Three options I see:

- Before the label and binding names, where inout appears today, and where other argument modifiers like `@autoclosure` go: func foo(&label x: Int)

which is the minimal change.

- Before the binding name: func foo(label &x: Int)

which is problematic for implicitly-labeled arguments.

- Before the type name: func foo(label x: &Int)

This is the most definition-follows-use-y, but would be inconsistent with other argument modifiers.

What is your suggested term for these kinds of parameters once we retire “inout”?

+1. Can you provide an example showing where you would place it though?

Good question. Three options I see:

- Before the label and binding names, where inout appears today, and where other argument modifiers like `@autoclosure` go: func foo(&label x: Int)

which is the minimal change.

- Before the binding name: func foo(label &x: Int)

which is problematic for implicitly-labeled arguments.

- Before the type name: func foo(label x: &Int)

This is the most definition-follows-use-y, but would be inconsistent with other argument modifiers.

It seems the latter is the only one of the three that would also make sense for function types. We still need to be able to write down a function type containing an inout parameter right?

Also your ideas for lenses involved inout return types — how would these fit in?

···

On Dec 18, 2015, at 5:30 PM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

On Dec 18, 2015, at 5:27 PM, Matthew Johnson <matthew@anandabits.com> wrote:

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

For Swift 3, we're planning to phase out 'var' parameters in functions, and we're also making it so that language keywords are valid argument labels. With both of these changes pending, I have a hard time not reading:

func foo(inout x: Int)

I don't think this would be a problem in practice since it is hard for me to imagine an API that would use 'inout' as a label -- at least they would spell it 'inOut' according to our API guidelines (but I really think they should call it something else).

My main concern is readability of the declaration. 'func foo(inout x: Int)' and 'func foo(label x: Int)' look very similar at a glance, but have totally different meanings. Going back to '@inout' like Slava suggested would be another possible improvement.

There's also a possibility that we add 'out' parameters in the future, and if 'inout' would be spelled '&', then we would need to find another sigil for 'out'.

We have multiple returns. Why would we ever add out parameters?

-Joe

···

On Dec 18, 2015, at 6:08 PM, Dmitri Gribenko <gribozavr@gmail.com> wrote:
On Fri, Dec 18, 2015 at 5:23 PM, Joe Groff via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

What would the ramifications of the following be? Each addresses the "confusable with labeling" issue but preserve the inout keyword.

func foo(x: inout Int)
func foo(x: @inout(Int))
func foo(x: @inout Int)

Is there an underlying reason that parameter modification should live on the name side rather than the type side of the colon? They aren't really modifying the name

-- Erica, inexperienced with Rust

···

On Dec 18, 2015, at 7:07 PM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

On Dec 18, 2015, at 5:23 PM, Joe Groff via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

For Swift 3, we're planning to phase out 'var' parameters in functions, and we're also making it so that language keywords are valid argument labels. With both of these changes pending, I have a hard time not reading:

func foo(inout x: Int)

as an argument labeled `inout` instead of an unlabeled argument bound to `x`. Once `var` is phased out, `inout` would also be the only remaining case where quoting is necessary to use a name as an argument label. The `inout` keyword has always struck me as weird, since it violates definition-follows-use—maybe we should replace it with the `&` sigil, mirroring its usage in call sites.

-1

“inout” is intended to communicate (or at least hint at) the copy-in / copy-out behavior of the argument. It is also there to enable other parameter modifiers, which can enable other more advanced parameters models in the future (e.g. rust-style borrowing).

-Chris

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

If we added those kinds of knobs, they'd almost certainly be @attributes IMO. A borrow model isn't really a core interface change the way `inout` is; it's a set of additional restrictions on use that let the compiler avoid unwanted retaining and copying.

-Joe

···

On Dec 18, 2015, at 6:07 PM, Chris Lattner <clattner@apple.com> wrote:

On Dec 18, 2015, at 5:23 PM, Joe Groff via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

For Swift 3, we're planning to phase out 'var' parameters in functions, and we're also making it so that language keywords are valid argument labels. With both of these changes pending, I have a hard time not reading:

func foo(inout x: Int)

as an argument labeled `inout` instead of an unlabeled argument bound to `x`. Once `var` is phased out, `inout` would also be the only remaining case where quoting is necessary to use a name as an argument label. The `inout` keyword has always struck me as weird, since it violates definition-follows-use—maybe we should replace it with the `&` sigil, mirroring its usage in call sites.

-1

“inout” is intended to communicate (or at least hint at) the copy-in / copy-out behavior of the argument. It is also there to enable other parameter modifiers, which can enable other more advanced parameters models in the future (e.g. rust-style borrowing).

I don't want to turn this thread into a discussion about out
parameters, but one reason would be to replace
AutoreleasingUnsafeMutablePointer. Another one is to add labels to
the output parameters:

let (day, month, year) = parseDate()
let (year, day, month) = parseDate() // bug?

Dmitri

···

On Fri, Dec 18, 2015 at 6:21 PM, Joe Groff <jgroff@apple.com> wrote:

On Dec 18, 2015, at 6:08 PM, Dmitri Gribenko <gribozavr@gmail.com> wrote:
There's also a possibility that we add 'out' parameters in the future, and
if 'inout' would be spelled '&', then we would need to find another sigil
for 'out'.

We have multiple returns. Why would we ever add out parameters?

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/

For Swift 3, we're planning to phase out 'var' parameters in functions, and we're also making it so that language keywords are valid argument labels. With both of these changes pending, I have a hard time not reading:

func foo(inout x: Int)

I don't think this would be a problem in practice since it is hard for me to imagine an API that would use 'inout' as a label -- at least they would spell it 'inOut' according to our API guidelines (but I really think they should call it something else).

My main concern is readability of the declaration. 'func foo(inout x: Int)' and 'func foo(label x: Int)' look very similar at a glance, but have totally different meanings. Going back to '@inout' like Slava suggested would be another possible improvement.

I wasn't thinking about the future with my initial vote. I definitely want to see a Rust-like ownership system someday and am excited to know that Chris is really interested in doing that eventually. It's probably best to do something that will fit into that world well. So maybe @inout is a better option.

···

Sent from my iPad

On Dec 18, 2015, at 8:21 PM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

On Dec 18, 2015, at 6:08 PM, Dmitri Gribenko <gribozavr@gmail.com> wrote:

On Fri, Dec 18, 2015 at 5:23 PM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

There's also a possibility that we add 'out' parameters in the future, and if 'inout' would be spelled '&', then we would need to find another sigil for 'out'.

We have multiple returns. Why would we ever add out parameters?

-Joe

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

-1 to using '&' in the declaration; it's a sigil that doesn't mean anything as is. (I was originally on the side of using 'inout' at the call site as well, i.e. "swap(inout x, inout y)", but it was considered too verbose.)

I don't like it as an attribute because attributes generally don't affect the syntax of how something is used; they're mostly just implementation detail. Obviously they can have important semantics (like "@objc(…)" controlling the selector, or '@convention(c)' for C-compatible function pointers), but for the most part they don't change what the declaration is, whereas 'inout' definitely does.

Given that we already use this syntax for function types when the parameter is unnamed, '(inout Int, inout named: Int) -> Void', I think Erica's first suggestion is my favorite so far.

Jordan

···

On Dec 19, 2015, at 16:10 , Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

What would the ramifications of the following be? Each addresses the "confusable with labeling" issue but preserve the inout keyword.

func foo(x: inout Int)
func foo(x: @inout(Int))
func foo(x: @inout Int)

Is there an underlying reason that parameter modification should live on the name side rather than the type side of the colon? They aren't really modifying the name

-- Erica, inexperienced with Rust

On Dec 18, 2015, at 7:07 PM, Chris Lattner via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Dec 18, 2015, at 5:23 PM, Joe Groff via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

For Swift 3, we're planning to phase out 'var' parameters in functions, and we're also making it so that language keywords are valid argument labels. With both of these changes pending, I have a hard time not reading:

func foo(inout x: Int)

as an argument labeled `inout` instead of an unlabeled argument bound to `x`. Once `var` is phased out, `inout` would also be the only remaining case where quoting is necessary to use a name as an argument label. The `inout` keyword has always struck me as weird, since it violates definition-follows-use—maybe we should replace it with the `&` sigil, mirroring its usage in call sites.

-1

“inout” is intended to communicate (or at least hint at) the copy-in / copy-out behavior of the argument. It is also there to enable other parameter modifiers, which can enable other more advanced parameters models in the future (e.g. rust-style borrowing).

-Chris

_______________________________________________
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

Putting `inout` after the colon feels good to me. Like Jordan said, it meshes better with the type syntax, (inout Int) -> (), too.

-Joe

···

On Dec 19, 2015, at 4:10 PM, Erica Sadun <erica@ericasadun.com> wrote:

What would the ramifications of the following be? Each addresses the "confusable with labeling" issue but preserve the inout keyword.

func foo(x: inout Int)
func foo(x: @inout(Int))
func foo(x: @inout Int)

Is there an underlying reason that parameter modification should live on the name side rather than the type side of the colon? They aren't really modifying the name

-- Erica, inexperienced with Rust

It depends on the details of the design. If something is currently borrowed “mut” then it can’t be used by anyone else. I’d want that “borrowing” action to be explicit in the code.

-Chris

···

On Dec 21, 2015, at 10:52 AM, Joe Groff <jgroff@apple.com> wrote:

-1

“inout” is intended to communicate (or at least hint at) the copy-in / copy-out behavior of the argument. It is also there to enable other parameter modifiers, which can enable other more advanced parameters models in the future (e.g. rust-style borrowing).

If we added those kinds of knobs, they'd almost certainly be @attributes IMO. A borrow model isn't really a core interface change the way `inout` is; it's a set of additional restrictions on use that let the compiler avoid unwanted retaining and copying.

I'd prefer `@inout` over `&x`.
It more clearly communicates its function and annotations already exist on parameters so it reuses that concept and has a clear location.

When using `@inout` I'm in favor of this change.

Although I'd like to point out that with syntax highlighting `inout` the keyword is clearly distinguishable from a parameter name.
But I don't mind typing an additional @ which is helpful for those situations without syntax highlighting and with the removal of `var` using an annotation seems more consistent.

- Janosch

There's also a possibility that we add 'out' parameters in the future, and
if 'inout' would be spelled '&', then we would need to find another sigil
for 'out'.

We have multiple returns. Why would we ever add out parameters?

I don't want to turn this thread into a discussion about out
parameters, but one reason would be to replace
AutoreleasingUnsafeMutablePointer. Another one is to add labels to
the output parameters:

let (day, month, year) = parseDate()
let (year, day, month) = parseDate() // bug?

I haven't had a need for multiple returns yet although I'm really glad they are in the language. They are much nicer than out parameters.

I'm really surprised if it isn't possible to use labeled tuples for multiple returns. It seems like that should be possible either now or in the future. (If I was at a computer right now I would try it)

···

On Dec 18, 2015, at 8:52 PM, Dmitri Gribenko via swift-evolution <swift-evolution@swift.org> wrote:

On Fri, Dec 18, 2015 at 6:21 PM, Joe Groff <jgroff@apple.com> wrote:
On Dec 18, 2015, at 6:08 PM, Dmitri Gribenko <gribozavr@gmail.com> wrote:

Dmitri

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I'd actually suggest that we reconsider this. '&' at the callsite has deep
associations with C semantics, and I have too frequently seen buggy code
using '&x' combined with one of the C interop implicit conversions to "get
a pointer" that the code stores in a variable somewhere. It is also hard
to explain to people that '&x' does not do what they want in that case, "&
means address-of, and it returns a pointer here, what do you mean I can't
use it?"

Dmitri

···

On Sat, Dec 19, 2015 at 7:06 PM, Jordan Rose via swift-evolution < swift-evolution@swift.org> wrote:

-1 to using '&' in the declaration; it's a sigil that doesn't mean
anything as is. (I was originally on the side of using 'inout' at the call
site as well, i.e. "swap(inout x, inout y)", but it was considered too
verbose.)

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/