From a88bfbb7e599cea6db1cabe3135921241ee1bc94 Mon Sep 17 00:00:00 2001 From: Joe Ranweiler Date: Tue, 19 Jul 2016 08:33:12 -0700 Subject: [PATCH 01/15] Add named-field-puns RFC draft --- text/0000-named-field-puns.md | 85 +++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 text/0000-named-field-puns.md diff --git a/text/0000-named-field-puns.md b/text/0000-named-field-puns.md new file mode 100644 index 00000000000..4a8ee3411dd --- /dev/null +++ b/text/0000-named-field-puns.md @@ -0,0 +1,85 @@ +- Feature Name: named-field-puns +- Start Date: 2016-07-18 +- RFC PR: (leave this empty) +- Rust Issue: (leave this empty) + +# Summary +[summary]: #summary + +When initializing a data structure (struct, enum, union) with named fields, allow writing `fieldname` as a shorthand for `fieldname: fieldname`. This allows a compact syntax for initialization, with less duplication: + + struct SomeStruct { field1: ComplexType, field2: AnotherType } + + impl SomeStruct { + fn new() -> Self { + let field1 = { + // Various initialization code + }; + let field2 = { + // More initialization code + }; + SomeStruct { complexField, anotherField } + } + } + +# Motivation +[motivation]: #motivation + +When writing initialization code for a data structure, the names of the structure fields often become the most straightforward names to use for their initial values as well. At the end of such an initialization function, then, the initializer will contain many patterns of repeated field names as field values: `field: field, field2: field2, field3: field3`. + +Such repetition of the field names makes it less ergonomic to separately declare and initialize individual fields, and makes it tempting to instead embed complex code directly in the initializer to avoid repetition. + +Rust already allows [similar syntax for destructuring in pattern matches](https://doc.rust-lang.org/book/patterns.html#destructuring): a pattern match can use `SomeStruct { field1, field2 } => ...` to match `field1` and `field2` into values with the same names. This RFC introduces symmetric syntax for initializers. + +A family of related structures will often use the same name for the same type of value. Combining this new syntax with the existing pattern-matching syntax allows simple movement of data between fields with a pattern match: `Struct1 { field1, .. } => Struct2 { field1 }`. + +The proposed syntax also improves structure initializers in closures, such as might appear in a chain of iterator adapters: `|field1, field2| SomeStruct { field1, field2 }`. + +This RFC takes inspiration from the Haskell [NamedFieldPuns extension](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#record-puns), and from ES6 [shorthand property names](http://www.ecma-international.org/ecma-262/6.0/#sec-object-initializer). + +# Detailed design +[design]: #detailed-design + +In the initializer for a `struct` with named fields, a `union` with named fields, or an enum variant with named fields, accept an identifier `field` as a shorthand for `field: field`. + +The shorthand initializer `field` always behaves in every possible way like the longhand initializer `field: field`. This RFC introduces no new behavior or semantics, only a purely syntactic shorthand. The rest of this section only provides further examples to explicitly clarify that this new syntax remains entirely orthogonal to other initializer behavior and semantics. + +If the struct `SomeStruct` has fields `field1` and `field2`, the initializer `SomeStruct { field1, field2 }` behaves in every way like the initializer `SomeStruct { field1: field1, field2: field2 }`. + +An initializer may contain any combination of shorthand and full field initializers: + + let a = SomeStruct { field1, field2: expression, field3 }; + let b = SomeStruct { field1: field1, field2: expression, field3: field3 }; + assert_eq!(a, b); + +An initializer may use shorthand field initializers together with [update syntax](https://doc.rust-lang.org/book/structs.html#update-syntax): + + let a = SomeStruct { field1, .. someStructInstance }; + let b = SomeStruct { field1: field1, .. someStructInstance }; + assert_eq!(a, b); + +This shorthand initializer syntax does not introduce any new compiler errors that cannot also occur with the longhand initializer syntax `field: field`. Existing compiler errors that can occur with the longhand initializer syntax `field: field` also apply to the shorthand initializer syntax `field`: + +- As with the longhand initializer `field: field`, if the structure has no field with the specified name `field`, the shorthand initializer `field` results in a compiler error for attempting to initialize a non-existent field. + +- As with the longhand initializer `field: field`, repeating a field name within the same initializer results in a compiler error ([E0062](https://doc.rust-lang.org/error-index.html#E0062)); this occurs with any combination of shorthand initializers or full `field: expression` initializers. + +- As with the longhand initializer `field: field`, if the name `field` does not resolve, the shorthand initializer `field` results in a compiler error for an unresolved name ([E0425](https://doc.rust-lang.org/error-index.html#E0425)). + +- As with the longhand initializer `field: field`, if the name `field` resolves to a value with type incompatible with the field `field` in the structure, the shorthand initializer `field` results in a compiler error for mismatched types ([E0308](https://doc.rust-lang.org/error-index.html#E0308)). + +# Drawbacks +[drawbacks]: #drawbacks + +This new syntax could significantly improve readability given clear and local field-punning variables, but could also be abused to decrease readability if used with more distant variables. + +As with many syntactic changes, a macro could implement this instead. See the Alternatives section for discussion of this. + +The shorthand initializer syntax looks similar to positional initialization of a structure without field names; reinforcing this, the initializer will commonly list the fields in the same order that the struct declares them. However, the shorthand initializer syntax differs from the positional initializer syntax (such as for a tuple struct) in that the positional syntax uses parentheses instead of braces: `SomeStruct(x, y)` is unambiguously a positional initializer, while `SomeStruct { x, y }` is unambiguously a shorthand initializer for the named fields `x` and `y`. + +# Alternatives +[alternatives]: #alternatives + +In addition to this syntax, initializers could support omitting the field names entirely, with syntax like `SomeStruct { .. }`, which would implicitly initialize omitted fields from identically named variables. However, that would introduce far too much magic into initializers, and the context-dependence seems likely to result in less readable, less obvious code. + +A macro wrapped around the initializer could implement this syntax, without changing the language; for instance, `pun! { SomeStruct { field1, field2 } }` could expand to `SomeStruct { field1: field1, field2: field2 }`. However, this change exists to make structure construction shorter and more expressive; having to use a macro would negate some of the benefit of doing so, particularly in places where brevity improves readability, such as in a closure in the middle of a larger expression. Pattern matching already allows using field names as the destination for the field values; this change adds a symmetrical mechanism for structure construction. \ No newline at end of file From 46a33d338f9c2975ca311472de876718b2cae1a9 Mon Sep 17 00:00:00 2001 From: Joe Ranweiler Date: Tue, 19 Jul 2016 09:13:36 -0700 Subject: [PATCH 02/15] Wrap words --- text/0000-named-field-puns.md | 113 +++++++++++++++++++++++++++------- 1 file changed, 90 insertions(+), 23 deletions(-) diff --git a/text/0000-named-field-puns.md b/text/0000-named-field-puns.md index 4a8ee3411dd..3d185a370e1 100644 --- a/text/0000-named-field-puns.md +++ b/text/0000-named-field-puns.md @@ -6,7 +6,9 @@ # Summary [summary]: #summary -When initializing a data structure (struct, enum, union) with named fields, allow writing `fieldname` as a shorthand for `fieldname: fieldname`. This allows a compact syntax for initialization, with less duplication: +When initializing a data structure (struct, enum, union) with named fields, +allow writing `fieldname` as a shorthand for `fieldname: fieldname`. This +allows a compact syntax for initialization, with less duplication: struct SomeStruct { field1: ComplexType, field2: AnotherType } @@ -25,61 +27,126 @@ When initializing a data structure (struct, enum, union) with named fields, allo # Motivation [motivation]: #motivation -When writing initialization code for a data structure, the names of the structure fields often become the most straightforward names to use for their initial values as well. At the end of such an initialization function, then, the initializer will contain many patterns of repeated field names as field values: `field: field, field2: field2, field3: field3`. +When writing initialization code for a data structure, the names of the +structure fields often become the most straightforward names to use for their +initial values as well. At the end of such an initialization function, then, +the initializer will contain many patterns of repeated field names as field +values: `field: field, field2: field2, field3: field3`. -Such repetition of the field names makes it less ergonomic to separately declare and initialize individual fields, and makes it tempting to instead embed complex code directly in the initializer to avoid repetition. +Such repetition of the field names makes it less ergonomic to separately +declare and initialize individual fields, and makes it tempting to instead +embed complex code directly in the initializer to avoid repetition. -Rust already allows [similar syntax for destructuring in pattern matches](https://doc.rust-lang.org/book/patterns.html#destructuring): a pattern match can use `SomeStruct { field1, field2 } => ...` to match `field1` and `field2` into values with the same names. This RFC introduces symmetric syntax for initializers. +Rust already allows +[similar syntax for destructuring in pattern matches](https://doc.rust-lang.org/book/patterns.html#destructuring): +a pattern match can use `SomeStruct { field1, field2 } => ...` to match +`field1` and `field2` into values with the same names. This RFC introduces +symmetric syntax for initializers. -A family of related structures will often use the same name for the same type of value. Combining this new syntax with the existing pattern-matching syntax allows simple movement of data between fields with a pattern match: `Struct1 { field1, .. } => Struct2 { field1 }`. +A family of related structures will often use the same name for the same type +of value. Combining this new syntax with the existing pattern-matching syntax +allows simple movement of data between fields with a pattern match: `Struct1 { +field1, .. } => Struct2 { field1 }`. -The proposed syntax also improves structure initializers in closures, such as might appear in a chain of iterator adapters: `|field1, field2| SomeStruct { field1, field2 }`. +The proposed syntax also improves structure initializers in closures, such as +might appear in a chain of iterator adapters: `|field1, field2| SomeStruct { +field1, field2 }`. -This RFC takes inspiration from the Haskell [NamedFieldPuns extension](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#record-puns), and from ES6 [shorthand property names](http://www.ecma-international.org/ecma-262/6.0/#sec-object-initializer). +This RFC takes inspiration from the Haskell +[NamedFieldPuns extension](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#record-puns), +and from ES6 +[shorthand property names](http://www.ecma-international.org/ecma-262/6.0/#sec-object-initializer). # Detailed design [design]: #detailed-design -In the initializer for a `struct` with named fields, a `union` with named fields, or an enum variant with named fields, accept an identifier `field` as a shorthand for `field: field`. +In the initializer for a `struct` with named fields, a `union` with named +fields, or an enum variant with named fields, accept an identifier `field` as a +shorthand for `field: field`. -The shorthand initializer `field` always behaves in every possible way like the longhand initializer `field: field`. This RFC introduces no new behavior or semantics, only a purely syntactic shorthand. The rest of this section only provides further examples to explicitly clarify that this new syntax remains entirely orthogonal to other initializer behavior and semantics. +The shorthand initializer `field` always behaves in every possible way like the +longhand initializer `field: field`. This RFC introduces no new behavior or +semantics, only a purely syntactic shorthand. The rest of this section only +provides further examples to explicitly clarify that this new syntax remains +entirely orthogonal to other initializer behavior and semantics. -If the struct `SomeStruct` has fields `field1` and `field2`, the initializer `SomeStruct { field1, field2 }` behaves in every way like the initializer `SomeStruct { field1: field1, field2: field2 }`. +If the struct `SomeStruct` has fields `field1` and `field2`, the initializer +`SomeStruct { field1, field2 }` behaves in every way like the initializer +`SomeStruct { field1: field1, field2: field2 }`. -An initializer may contain any combination of shorthand and full field initializers: +An initializer may contain any combination of shorthand and full field +initializers: let a = SomeStruct { field1, field2: expression, field3 }; let b = SomeStruct { field1: field1, field2: expression, field3: field3 }; assert_eq!(a, b); -An initializer may use shorthand field initializers together with [update syntax](https://doc.rust-lang.org/book/structs.html#update-syntax): +An initializer may use shorthand field initializers together with +[update syntax](https://doc.rust-lang.org/book/structs.html#update-syntax): let a = SomeStruct { field1, .. someStructInstance }; let b = SomeStruct { field1: field1, .. someStructInstance }; assert_eq!(a, b); -This shorthand initializer syntax does not introduce any new compiler errors that cannot also occur with the longhand initializer syntax `field: field`. Existing compiler errors that can occur with the longhand initializer syntax `field: field` also apply to the shorthand initializer syntax `field`: +This shorthand initializer syntax does not introduce any new compiler errors +that cannot also occur with the longhand initializer syntax `field: field`. +Existing compiler errors that can occur with the longhand initializer syntax +`field: field` also apply to the shorthand initializer syntax `field`: -- As with the longhand initializer `field: field`, if the structure has no field with the specified name `field`, the shorthand initializer `field` results in a compiler error for attempting to initialize a non-existent field. +- As with the longhand initializer `field: field`, if the structure has no + field with the specified name `field`, the shorthand initializer `field` + results in a compiler error for attempting to initialize a non-existent + field. -- As with the longhand initializer `field: field`, repeating a field name within the same initializer results in a compiler error ([E0062](https://doc.rust-lang.org/error-index.html#E0062)); this occurs with any combination of shorthand initializers or full `field: expression` initializers. +- As with the longhand initializer `field: field`, repeating a field name + within the same initializer results in a compiler error + ([E0062](https://doc.rust-lang.org/error-index.html#E0062)); this occurs with + any combination of shorthand initializers or full `field: expression` + initializers. -- As with the longhand initializer `field: field`, if the name `field` does not resolve, the shorthand initializer `field` results in a compiler error for an unresolved name ([E0425](https://doc.rust-lang.org/error-index.html#E0425)). +- As with the longhand initializer `field: field`, if the name `field` does not + resolve, the shorthand initializer `field` results in a compiler error for an + unresolved name ([E0425](https://doc.rust-lang.org/error-index.html#E0425)). -- As with the longhand initializer `field: field`, if the name `field` resolves to a value with type incompatible with the field `field` in the structure, the shorthand initializer `field` results in a compiler error for mismatched types ([E0308](https://doc.rust-lang.org/error-index.html#E0308)). +- As with the longhand initializer `field: field`, if the name `field` resolves + to a value with type incompatible with the field `field` in the structure, + the shorthand initializer `field` results in a compiler error for mismatched + types ([E0308](https://doc.rust-lang.org/error-index.html#E0308)). # Drawbacks [drawbacks]: #drawbacks -This new syntax could significantly improve readability given clear and local field-punning variables, but could also be abused to decrease readability if used with more distant variables. +This new syntax could significantly improve readability given clear and local +field-punning variables, but could also be abused to decrease readability if +used with more distant variables. -As with many syntactic changes, a macro could implement this instead. See the Alternatives section for discussion of this. +As with many syntactic changes, a macro could implement this instead. See the +Alternatives section for discussion of this. -The shorthand initializer syntax looks similar to positional initialization of a structure without field names; reinforcing this, the initializer will commonly list the fields in the same order that the struct declares them. However, the shorthand initializer syntax differs from the positional initializer syntax (such as for a tuple struct) in that the positional syntax uses parentheses instead of braces: `SomeStruct(x, y)` is unambiguously a positional initializer, while `SomeStruct { x, y }` is unambiguously a shorthand initializer for the named fields `x` and `y`. +The shorthand initializer syntax looks similar to positional initialization of +a structure without field names; reinforcing this, the initializer will +commonly list the fields in the same order that the struct declares them. +However, the shorthand initializer syntax differs from the positional +initializer syntax (such as for a tuple struct) in that the positional syntax +uses parentheses instead of braces: `SomeStruct(x, y)` is unambiguously a +positional initializer, while `SomeStruct { x, y }` is unambiguously a +shorthand initializer for the named fields `x` and `y`. # Alternatives [alternatives]: #alternatives -In addition to this syntax, initializers could support omitting the field names entirely, with syntax like `SomeStruct { .. }`, which would implicitly initialize omitted fields from identically named variables. However, that would introduce far too much magic into initializers, and the context-dependence seems likely to result in less readable, less obvious code. - -A macro wrapped around the initializer could implement this syntax, without changing the language; for instance, `pun! { SomeStruct { field1, field2 } }` could expand to `SomeStruct { field1: field1, field2: field2 }`. However, this change exists to make structure construction shorter and more expressive; having to use a macro would negate some of the benefit of doing so, particularly in places where brevity improves readability, such as in a closure in the middle of a larger expression. Pattern matching already allows using field names as the destination for the field values; this change adds a symmetrical mechanism for structure construction. \ No newline at end of file +In addition to this syntax, initializers could support omitting the field names +entirely, with syntax like `SomeStruct { .. }`, which would implicitly +initialize omitted fields from identically named variables. However, that would +introduce far too much magic into initializers, and the context-dependence +seems likely to result in less readable, less obvious code. + +A macro wrapped around the initializer could implement this syntax, without +changing the language; for instance, `pun! { SomeStruct { field1, field2 } }` +could expand to `SomeStruct { field1: field1, field2: field2 }`. However, this +change exists to make structure construction shorter and more expressive; +having to use a macro would negate some of the benefit of doing so, +particularly in places where brevity improves readability, such as in a closure +in the middle of a larger expression. Pattern matching already allows using +field names as the destination for the field values; this change adds a +symmetrical mechanism for structure construction. From f8e50c541f7484481e43055a0c6fc59047c1a35c Mon Sep 17 00:00:00 2001 From: Joe Ranweiler Date: Tue, 19 Jul 2016 09:20:15 -0700 Subject: [PATCH 03/15] Caption example usage in summary --- text/0000-named-field-puns.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/text/0000-named-field-puns.md b/text/0000-named-field-puns.md index 3d185a370e1..813c18d97ed 100644 --- a/text/0000-named-field-puns.md +++ b/text/0000-named-field-puns.md @@ -8,7 +8,9 @@ When initializing a data structure (struct, enum, union) with named fields, allow writing `fieldname` as a shorthand for `fieldname: fieldname`. This -allows a compact syntax for initialization, with less duplication: +allows a compact syntax for initialization, with less duplication. + +Example usage: struct SomeStruct { field1: ComplexType, field2: AnotherType } From bd201d64ba40c04547ed4dc1a6095d4d7e32ce29 Mon Sep 17 00:00:00 2001 From: Joe Ranweiler Date: Tue, 19 Jul 2016 09:20:39 -0700 Subject: [PATCH 04/15] Remove non-technical use of the word "type" --- text/0000-named-field-puns.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/text/0000-named-field-puns.md b/text/0000-named-field-puns.md index 813c18d97ed..ad743e6a037 100644 --- a/text/0000-named-field-puns.md +++ b/text/0000-named-field-puns.md @@ -45,10 +45,10 @@ a pattern match can use `SomeStruct { field1, field2 } => ...` to match `field1` and `field2` into values with the same names. This RFC introduces symmetric syntax for initializers. -A family of related structures will often use the same name for the same type -of value. Combining this new syntax with the existing pattern-matching syntax -allows simple movement of data between fields with a pattern match: `Struct1 { -field1, .. } => Struct2 { field1 }`. +A family of related structures will often use the same field name for a +semantically-shared value. Combining this new syntax with the existing +pattern-matching syntax allows simple movement of data between fields with a +pattern match: `Struct1 { field1, .. } => Struct2 { field1 }`. The proposed syntax also improves structure initializers in closures, such as might appear in a chain of iterator adapters: `|field1, field2| SomeStruct { From 96bcd13fec834f7f39c82ff76e35ca307f90781d Mon Sep 17 00:00:00 2001 From: Joe Ranweiler Date: Tue, 19 Jul 2016 09:27:46 -0700 Subject: [PATCH 05/15] Tweak adjective --- text/0000-named-field-puns.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-named-field-puns.md b/text/0000-named-field-puns.md index ad743e6a037..5dd0be82cb4 100644 --- a/text/0000-named-field-puns.md +++ b/text/0000-named-field-puns.md @@ -43,7 +43,7 @@ Rust already allows [similar syntax for destructuring in pattern matches](https://doc.rust-lang.org/book/patterns.html#destructuring): a pattern match can use `SomeStruct { field1, field2 } => ...` to match `field1` and `field2` into values with the same names. This RFC introduces -symmetric syntax for initializers. +symmetrical syntax for initializers. A family of related structures will often use the same field name for a semantically-shared value. Combining this new syntax with the existing From 379e50acb34351043b221c95966a49e8313a8401 Mon Sep 17 00:00:00 2001 From: Joe Ranweiler Date: Tue, 19 Jul 2016 09:30:16 -0700 Subject: [PATCH 06/15] Emphasize precedent and symmetry when assessing macros --- text/0000-named-field-puns.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/text/0000-named-field-puns.md b/text/0000-named-field-puns.md index 5dd0be82cb4..5798f917cd2 100644 --- a/text/0000-named-field-puns.md +++ b/text/0000-named-field-puns.md @@ -149,6 +149,7 @@ could expand to `SomeStruct { field1: field1, field2: field2 }`. However, this change exists to make structure construction shorter and more expressive; having to use a macro would negate some of the benefit of doing so, particularly in places where brevity improves readability, such as in a closure -in the middle of a larger expression. Pattern matching already allows using -field names as the destination for the field values; this change adds a -symmetrical mechanism for structure construction. +in the middle of a larger expression. There is also precedent for +language-level support. Pattern matching already allows using field names as +the _destination_ for the field values via destructuring. This change adds a +symmetrical mechanism for construction which uses existing names as _sources_. From f9827d1847c37ffc782cf583a7ab8228f2475b0a Mon Sep 17 00:00:00 2001 From: Joe Ranweiler Date: Tue, 19 Jul 2016 10:13:26 -0700 Subject: [PATCH 07/15] Fix field names in example --- text/0000-named-field-puns.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-named-field-puns.md b/text/0000-named-field-puns.md index 5798f917cd2..1fd3ff7f6f7 100644 --- a/text/0000-named-field-puns.md +++ b/text/0000-named-field-puns.md @@ -22,7 +22,7 @@ Example usage: let field2 = { // More initialization code }; - SomeStruct { complexField, anotherField } + SomeStruct { field1, field2 } } } From 8c307c1e10b28d65afe21c77d858f853a0bae1f3 Mon Sep 17 00:00:00 2001 From: Joe Ranweiler Date: Tue, 19 Jul 2016 11:56:44 -0700 Subject: [PATCH 08/15] Use "similar" to avoid conflation with senses of "shared" --- text/0000-named-field-puns.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-named-field-puns.md b/text/0000-named-field-puns.md index 1fd3ff7f6f7..d528630f50b 100644 --- a/text/0000-named-field-puns.md +++ b/text/0000-named-field-puns.md @@ -46,7 +46,7 @@ a pattern match can use `SomeStruct { field1, field2 } => ...` to match symmetrical syntax for initializers. A family of related structures will often use the same field name for a -semantically-shared value. Combining this new syntax with the existing +semantically-similar value. Combining this new syntax with the existing pattern-matching syntax allows simple movement of data between fields with a pattern match: `Struct1 { field1, .. } => Struct2 { field1 }`. From 66b2a82f64c4dcdc715d13bfbb89a7f99c93e0f4 Mon Sep 17 00:00:00 2001 From: Joe Ranweiler Date: Tue, 19 Jul 2016 17:12:28 -0700 Subject: [PATCH 09/15] Add subsections to "Alternatives" section --- text/0000-named-field-puns.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/text/0000-named-field-puns.md b/text/0000-named-field-puns.md index d528630f50b..2b73c38cc47 100644 --- a/text/0000-named-field-puns.md +++ b/text/0000-named-field-puns.md @@ -137,12 +137,16 @@ shorthand initializer for the named fields `x` and `y`. # Alternatives [alternatives]: #alternatives +## Wildcards + In addition to this syntax, initializers could support omitting the field names entirely, with syntax like `SomeStruct { .. }`, which would implicitly initialize omitted fields from identically named variables. However, that would introduce far too much magic into initializers, and the context-dependence seems likely to result in less readable, less obvious code. +## Macros + A macro wrapped around the initializer could implement this syntax, without changing the language; for instance, `pun! { SomeStruct { field1, field2 } }` could expand to `SomeStruct { field1: field1, field2: field2 }`. However, this From 7cfd7e9053532c12cbe9d0cbf61f528ce43f77f3 Mon Sep 17 00:00:00 2001 From: Joe Ranweiler Date: Tue, 19 Jul 2016 17:12:42 -0700 Subject: [PATCH 10/15] Add subsection for sigil alternative --- text/0000-named-field-puns.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/text/0000-named-field-puns.md b/text/0000-named-field-puns.md index 2b73c38cc47..e630b9f1263 100644 --- a/text/0000-named-field-puns.md +++ b/text/0000-named-field-puns.md @@ -157,3 +157,26 @@ in the middle of a larger expression. There is also precedent for language-level support. Pattern matching already allows using field names as the _destination_ for the field values via destructuring. This change adds a symmetrical mechanism for construction which uses existing names as _sources_. + + +## Sigils + +To minimize confusing shorthand expressions with the construction of +tuple-like structs, we might elect to prefix expanded field names with +sigils. + +For example, if the sigil were `:`, the existing syntax `S { x: x }` +would be expressed as `S { :x }`. This is used in +[MoonScript](http://moonscript.org/reference/#the-language/table-literals). + +This particular choice of sigil may be confusing, due to the +already-overloaded use of `:` for fields and type ascription. Additionally, +in languages such as Ruby and Elixir, `:x` denotes a symbol or atom, which +may be confusing for newcomers. + +Other sigils could be used instead, but even then we are then increasing +the amount of new syntax being introduced. This both increases language +complexity and reduces the gained compactness, worsening the +cost/benefit ratio of adding a shorthand. Any use of a sigil also breaks +the symmetry between binding pattern matching and the proposed +shorthand. From 42f4035dd4af2ded018a221e8b0a9b4dc6e7b7ec Mon Sep 17 00:00:00 2001 From: Ryan Scheel Date: Tue, 19 Jul 2016 17:04:35 -0700 Subject: [PATCH 11/15] Explicit type punning alternative. --- text/0000-named-field-puns.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/text/0000-named-field-puns.md b/text/0000-named-field-puns.md index e630b9f1263..dcfbb9c8af0 100644 --- a/text/0000-named-field-puns.md +++ b/text/0000-named-field-puns.md @@ -158,7 +158,6 @@ language-level support. Pattern matching already allows using field names as the _destination_ for the field values via destructuring. This change adds a symmetrical mechanism for construction which uses existing names as _sources_. - ## Sigils To minimize confusing shorthand expressions with the construction of @@ -180,3 +179,19 @@ complexity and reduces the gained compactness, worsening the cost/benefit ratio of adding a shorthand. Any use of a sigil also breaks the symmetry between binding pattern matching and the proposed shorthand. + +## Keyword-prefixed + +Similarly to sigils, we could use a keyword like Nix uses +[inherit](http://nixos.org/nix/manual/#idm46912467627696). Some forms we could +decide upon (using `use` as the keyword of choice here, but it could be +something else), it could look like the following. + +* `S { use x, y, z: 10}` +* `S { use (x, y), z: 10 }` +* `S { use {x, y}, z: 10 }` +* `S { use x, use y, z: 10}` + +This has the same drawbacks as sigils except that it won't be confused for +symbols in other languages or adding more sigils. It also has the benefit +of being something that can be searched for in documentation. \ No newline at end of file From ec7f3b1782d3295767fbd5dfc21a499e65e8a797 Mon Sep 17 00:00:00 2001 From: Joe Ranweiler Date: Sat, 23 Jul 2016 12:48:10 -0700 Subject: [PATCH 12/15] Add subsections to "Detailed design" section --- text/0000-named-field-puns.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/text/0000-named-field-puns.md b/text/0000-named-field-puns.md index dcfbb9c8af0..4d63907612f 100644 --- a/text/0000-named-field-puns.md +++ b/text/0000-named-field-puns.md @@ -62,16 +62,22 @@ and from ES6 # Detailed design [design]: #detailed-design +## Grammar + In the initializer for a `struct` with named fields, a `union` with named fields, or an enum variant with named fields, accept an identifier `field` as a shorthand for `field: field`. +## Interpretation + The shorthand initializer `field` always behaves in every possible way like the longhand initializer `field: field`. This RFC introduces no new behavior or semantics, only a purely syntactic shorthand. The rest of this section only provides further examples to explicitly clarify that this new syntax remains entirely orthogonal to other initializer behavior and semantics. +## Examples + If the struct `SomeStruct` has fields `field1` and `field2`, the initializer `SomeStruct { field1, field2 }` behaves in every way like the initializer `SomeStruct { field1: field1, field2: field2 }`. @@ -90,6 +96,8 @@ An initializer may use shorthand field initializers together with let b = SomeStruct { field1: field1, .. someStructInstance }; assert_eq!(a, b); +## Compilation errors + This shorthand initializer syntax does not introduce any new compiler errors that cannot also occur with the longhand initializer syntax `field: field`. Existing compiler errors that can occur with the longhand initializer syntax From 23b91944e517ddde4637aedabd2b93b54ea78d2c Mon Sep 17 00:00:00 2001 From: Joe Ranweiler Date: Sat, 23 Jul 2016 12:48:25 -0700 Subject: [PATCH 13/15] Fix EOF newline --- text/0000-named-field-puns.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-named-field-puns.md b/text/0000-named-field-puns.md index 4d63907612f..ccec3462c7a 100644 --- a/text/0000-named-field-puns.md +++ b/text/0000-named-field-puns.md @@ -202,4 +202,4 @@ something else), it could look like the following. This has the same drawbacks as sigils except that it won't be confused for symbols in other languages or adding more sigils. It also has the benefit -of being something that can be searched for in documentation. \ No newline at end of file +of being something that can be searched for in documentation. From 7016ba90bdd59df611a703f342a3f4fe186197a7 Mon Sep 17 00:00:00 2001 From: Joe Ranweiler Date: Sat, 23 Jul 2016 12:48:51 -0700 Subject: [PATCH 14/15] Add description of formal grammar change --- text/0000-named-field-puns.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/text/0000-named-field-puns.md b/text/0000-named-field-puns.md index ccec3462c7a..67eb08b7e92 100644 --- a/text/0000-named-field-puns.md +++ b/text/0000-named-field-puns.md @@ -68,6 +68,16 @@ In the initializer for a `struct` with named fields, a `union` with named fields, or an enum variant with named fields, accept an identifier `field` as a shorthand for `field: field`. +With reference to the grammar in `parser-lalr.y`, this proposal would +expand the `field_init` +[rule](https://github.com/rust-lang/rust/blob/master/src/grammar/parser-lalr.y#L1663-L1665) +to the following: + + field_init + : ident + | ident ':' expr + ; + ## Interpretation The shorthand initializer `field` always behaves in every possible way like the From b425e052fb2544ff01c127cf3c0f24089ada492a Mon Sep 17 00:00:00 2001 From: Joe Ranweiler Date: Tue, 4 Oct 2016 13:11:14 -0700 Subject: [PATCH 15/15] Rename feature to "field-init-shorthand" --- text/{0000-named-field-puns.md => 0000-field-init-shorthand.md} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename text/{0000-named-field-puns.md => 0000-field-init-shorthand.md} (99%) diff --git a/text/0000-named-field-puns.md b/text/0000-field-init-shorthand.md similarity index 99% rename from text/0000-named-field-puns.md rename to text/0000-field-init-shorthand.md index 67eb08b7e92..e86861cc029 100644 --- a/text/0000-named-field-puns.md +++ b/text/0000-field-init-shorthand.md @@ -1,4 +1,4 @@ -- Feature Name: named-field-puns +- Feature Name: field-init-shorthand - Start Date: 2016-07-18 - RFC PR: (leave this empty) - Rust Issue: (leave this empty)