Why can the assignment operator be chained in Rust?
Asked Answered
F

2

6

Rust has several operators that cannot be chained (==, < for example).

But the assignment operator = can be chained.

a = b = 10;

In this case, 10 is assigned to b, and unit () is assigned to a.

Is there any reason why Rust allows us to chain = like this?

I created Clippy issue 6576 about this.

Fan answered 11/1, 2021 at 4:59 Comment(9)
Assign a single value to multiple variables in one line in Rust?Culpepper
Assignments are expressions to allow using them in expression context, e.g. as the result expression in a match arm. Assignments may not be useful everywhere an expression is expected – e.g. on the right-hand side of another assignment, or as an argument to a function. However, I don't see any reaon to explicitly prohibit assignments in these cases – you will get a compiler error anyway, unless a is expected to be of type ().Hoicks
I don't think there is any more to this design decision – it seems useful that assignments are expressions, and it doesn't seem necessary to explicitly prohibit them in contexts where they don't make much sense. Questions about language design decisions are often a bit hard to answer, since we don't always have insight into how this decision was originally made, in particular for decisions made very early in the design of a language.Hoicks
See the original RFC Require parenthesis for chained comparisons for motivation.Tony
@Tony As far as I can tell, that RFC is only about comparison operators, not about assignments.Hoicks
@SvenMarnach right, but it could provide some context. Most other operators can be chained (like a + b + c), so since there's an RFC specifically for the comparison operators it indicates that the assignment's behavior is the default rather than an exception. That and the provided motivation for restricting the comparison operators wouldn't apply to assignments.Tony
Fair enough. Assignment operators are kind of special, since they are the only operators in Rust that have right-to-left associativity, so their behaviour isn't really the "default". I still don't think a lot of thought went into that design – there just isn't a strong reason to prohibit assignment operator chaining, in spite of its pointlessness.Hoicks
There is one reason I can think of to not have chaining of assignment: Unless the type is copyable (or a constant expression, maybe?), assignment chaining would (at least in the most straight-forward behavior) assign a value and then have to immediately (attempt to) move out the same value again. So it would either be mostly useless or not work at all for non-copyable types.Jeffiejeffrey
Does this answer your question? Assign a single value to multiple variables in one line in Rust?Culpepper
M
1

Almost everything in Rust is an expression and not a statement. The major difference between statements and expressions is that expressions return a value after they execute.

This too holds for assignment operations, which are treated as expressions in Rust. The assignment expression has the return value (), also called unit value. What effect does that have on your program?

This means that your assignment

a = b = 10

is parsed as

a = (b = 10)

Note that the return value of b = 10 is () (since it is an expression), and thus this return value gets assigned to a.

Mendacious answered 11/1, 2021 at 13:0 Comment(5)
The fact that the operator = is right-associative, does not make sense to me. Are there any problems if = is not right-associative?Fan
If you look from left to right, what is happening is basically you are trying to assign something to a, that thing is an expression, so you evaluate it ( which in effect assigns to b ), and then you assign the value of expression.Mendacious
@Fan if = is left-associative then a = b = c = 10 will be parsed as ((a = b) = c) =10 which makes zero senseCulpepper
I'm not talking about right-associative or left-associative, but associative or not associative.Fan
@Fan how can that even work? How would you group multiple operators with the same precedence. Example of = (assignment) being right-associativeCulpepper
C
1

Here is one reason I can think of. Having assignment as an expression allows for more streamlined syntax in some cases.

match x {
    Some(b) => a = b,
    None => a = 1,
}

Otherwise, the above would have to be written as:

match x {
    Some(b) => {
        a = b;
    },
    None => {
        a = 1;
    },
}
Cellulous answered 12/1, 2021 at 16:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.