为啥赋值运算符可以在 Rust 中被链接?

Posted

技术标签:

【中文标题】为啥赋值运算符可以在 Rust 中被链接?【英文标题】:Why can the assignment operator be chained in Rust?为什么赋值运算符可以在 Rust 中被链接? 【发布时间】:2021-04-16 01:56:51 【问题描述】:

Rust 有几个无法链接的运算符(例如==<)。

但是赋值运算符=可以链接起来。

a = b = 10;

在这种情况下,10 分配给b,单位() 分配给a

Rust 允许我们像这样链接= 有什么原因吗?

我为此创建了Clippy issue 6576。

【问题讨论】:

Assign a single value to multiple variables in one line in Rust? 赋值是允许在表达式上下文中使用它们的表达式,例如作为匹配臂中的结果表达式。赋值可能不是有用的在任何地方都需要一个表达式——例如在另一个赋值的右侧,或作为函数的参数。但是,在这些情况下,我看不出有任何明确禁止赋值的理由——无论如何你都会得到一个编译器错误,除非a 应该是() 类型。 我认为这个设计决策没有更多意义——赋值是表达式似乎很有用,而且似乎没有必要在它们没有多大作用的上下文中明确禁止它们感觉。关于语言设计决策的问题通常有点难以回答,因为我们并不总是了解最初是如何做出这个决定的,尤其是在语言设计的早期做出的决定。 查看原始 RFC Require parenthesis for chained comparisons 以获得动机。 @kmdreko 据我所知,RFC 仅涉及比较运算符,而不涉及分配。 【参考方案1】:

Rust 中几乎所有的东西都是表达式而不是语句。语句和表达式的主要区别在于表达式在执行后返回一个值。

这也适用于赋值操作,它们在 Rust 中被视为表达式。赋值表达式有返回值(),也叫单位值。这对您的程序有什么影响?

这意味着你的任务

a = b = 10

被解析为

a = (b = 10)

注意b = 10的返回值是()(因为它是一个表达式),因此这个返回值被赋值给a

【讨论】:

运算符= 是右关联的这一事实对我来说没有意义。如果= 不是右关联的,会有什么问题吗? 如果你从左到右看,发生的事情基本上是你试图给a分配一些东西,那个东西是一个表达式,所以你评估它(实际上分配给b) ,然后分配表达式的值。 @fiveseven 如果= 是左关联的,那么a = b = c = 10 将被解析为((a = b) = c) =10,这是零意义 我不是在谈论右关联或左关联,而是关联或非关联。 @fiveseven 这怎么行?您如何将具有相同优先级的多个运算符分组。 Example of = (assignment) being right-associative【参考方案2】:

这是我能想到的一个原因。在某些情况下,将赋值作为表达式允许更精简的语法。

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

否则,以上内容必须写成:

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

【讨论】:

以上是关于为啥赋值运算符可以在 Rust 中被链接?的主要内容,如果未能解决你的问题,请参考以下文章

为啥短原语有赋值运算符(&=、+=)但没有非赋值运算符(&、+)? [复制]

为啥我们在赋值运算符重载中使用引用返回而不是在加减运算中?

为啥移动赋值运算符应该返回对 *this 的引用 [重复]

为啥 ~= 在 C++ 中缺少唯一的非逻辑赋值运算符? [关闭]

为啥你可以在函数中使用另一种方法而不是赋值运算符来更改 Ruby 中局部变量的值?

为啥使用单个赋值运算符处理复制和移动赋值效率不高?