Skip to content

Commit a888410

Browse files
authored
update "Struct initializers in Rust"
1 parent 173689b commit a888410

File tree

1 file changed

+52
-6
lines changed

1 file changed

+52
-6
lines changed

_languages/rust-struct-initializer-mistake.md

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,10 @@ struct User(
9292
active: bool,
9393
sign_in_count: u64 = 0) // default parameter value
9494

95+
struct State(active: bool)
96+
9597
fn user(username: String, email: String) -> User {
96-
User(username, email, active = true) // named parameter
98+
User(username, email, active = State(true)) // named parameter
9799
}
98100

99101
fn main() {
@@ -107,15 +109,59 @@ Example:
107109

108110
fun someFunction(a: Int64) = ...
109111
var a = 12;
110-
let b = 23
111-
someFunction(a = b) // what does this mean?
112+
someFunction(a = 23) // what does this mean?
113+
114+
Two points have to be considered here:
115+
116+
1. Reducing chances of mix-ups:
117+
- Frequency: Are variable assignments within function calls or function calls with named parameters projected to be used more often?
118+
- Intuitivity: How can the syntax be distributed to those two use-cases such that the configuration makes sense from a user point-of-view?
119+
2. Reducing the harm from mix-ups:
120+
- Can code that looks correct behave unexpectedly
121+
122+
In general, there are multiple options:
123+
124+
###### Try to use the same syntax for both variable assigments and named parameters
125+
126+
This means that named parameters simply act like another scope in which identifiers are looked up.
127+
128+
The danger with this approach is that changing the name of a named parameter can silently change the meaning of callsites if a variable with the previously used parameter name happens to be in scope.
129+
130+
// named parameter, but if someFunction's parameter name changes,
131+
// without the callsite being updated, it silently becomes an
132+
// assignment instead of a compilation failure:
133+
someFunction(a = 23)
134+
135+
It also means that variables with the same name as a parameter name cannot be assigned within a function call.
136+
137+
###### Let variable assignments use the "good" syntax and give named parameters some workaround syntax
138+
139+
In this example, the orkaround syntax for named parameters is a `.` prefixed to the parameter name.
140+
141+
// variable assigment inside a function argument list,
142+
// only works if assignment returns the assigned value
143+
// (which is generally a bad idea):
144+
someFunction(a = 23)
145+
146+
// named parameter, and if someFunction's parameter name changes,
147+
// without the callsite being updated, it becomes a compilation failure:
148+
someFunction(.a = 23)
149+
150+
151+
152+
###### Let named parameters use the "good" syntax and give variable assignments some workaround syntax
112153

113-
Single rule: inside a functions argument list, the first level of `=` use is always a named parameter and never a
154+
Inside a functions argument list, the first level of `=` use is always a named parameter and never a
114155
variable assignment, even if some variable `a` would be in scope.[^2]
115156

116-
If a variable assigment inside a function argument list is still needed, it could be expressed as:
157+
// named parameter, and if someFunction's parameter name changes,
158+
// without the callsite being updated, it becomes a compilation failure:
159+
someFunction(a = 23)
117160

118-
someFunction(a = { a = b; b }) // still possible
161+
// variable assigment inside a function argument list,
162+
// only works if assignment returns the assigned value
163+
// (which is generally a bad idea):
164+
someFunction(a = { a = 23 })
119165

120166

121167
[^1]: Except the tupled version of enums, for which initializers look like function calls again.

0 commit comments

Comments
 (0)