【问题标题】:What is the meaning of the error "left-hand of expression not valid"?错误“表达式的左手无效”是什么意思?
【发布时间】:2019-03-17 07:32:09
【问题描述】:

我编写这段代码是为了看看当我将两个字符串传递给一个函数并再次返回它们时会发生什么:

fn main() {
    let mut s3 = String::from("hello");
    let mut s4 = String::from("wolrd");

    (s3, s4) = take_n_giveback(s3, s4);

    println!("{0} and {1}", s3, s4);
}

fn take_n_giveback(x: String, y: String) -> (String, String) {
    (x, y)
}

我收到一个无用的错误:

error[E0070]: invalid left-hand side expression
 --> src/main.rs:5:5
  |
5 |     (s3, s4) = take_n_giveback(s3, s4);
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ left-hand of expression not valid

此操作在传递单个字符串并返回时工作正常。

fn main() {
    let mut s3 = String::from("hello");
    s3 = take_n_giveback(s3);
    println!("{0} ", s3);
}

fn take_n_giveback(x: String) -> (String) {
    x
}

这里有什么问题?错误是什么意思,在代码中会遇到什么情况?

【问题讨论】:

  • 绑定值时必须使用let,例如let (s3, s4) = ...
  • 正如我提到的,它适用于单个变量而不使用 let 关键字。那么这是如何发生的。
  • 这个例子对我来说似乎有点复杂,因为我是初学者,你能解释一下更新问题中第一个(不工作)和第二个例子(工作)之间的根本区别吗?
  • 请花时间返回并重新阅读The Rust Programming Language,特别是section on variables。本书涵盖了许多介绍性主题,例如介绍性语法。

标签: rust ownership


【解决方案1】:
let ... = ... // or let mut

是一个绑定:它创建新变量。

... = ...

(没有let)是一个赋值:它改变已经绑定的变量(或其部分)的值。有关此差异的更多说明,请参阅What's the semantic of assignment in Rust?

绑定的左手必须是模式;赋值的左边必须是 place 表达式(以前称为左值)。如https://doc.rust-lang.org/reference/expressions.html#place-expressions-and-value-expressions

中所述

位置表达式是表示内存位置的表达式。这些表达式是引用局部变量、静态变量、取消引用 (*expr)、数组索引表达式 (expr[expr])、字段引用 (expr.f) 和带括号的位置表达式的路径。所有其他表达式都是值表达式。

(s3, s4) 是一个模式,但它不是一个位置表达式,因为它不是上述之一;它不代表一个固定的内存位置。

此操作在传递单个字符串并返回时工作正常。

变量名称,如s3,既可以用作模式,也可以用作位置表达式。但有不同的含义!在作业中使用时

let mut s3 = String::from("hello");
s3 = take_n_giveback(s3);

它代表let mut s3声明的变量的位置,所以只有一个变量;但是在

let mut s3 = String::from("hello");
let s3 = take_n_giveback(s3);

它创建了一个名为s3 的新变量,因此有两个不同的变量恰好具有相同的名称。这就是为什么即使第一个不是 mut 也能正常工作的原因。

【讨论】:

  • 虽然我已经理解它是如何工作的,但是你能解释一下当我们写 let (s3, s4) = take_n_giveback(s3, s4) 时它是如何得到一个固定位置的吗?是不是就像我们使用“let”创建绑定时,rust 分配了连续的内存位置 s3 和 s4,然后它变成了左值?
  • let 使用模式,而不是左值,因此这里的(s3, s4) 根本不需要固定位置。它确实为s3s4 分配内存位置(在堆栈上),但我不知道它们是否能保证相互跟随。
  • 也许考虑一些左值但不是模式的东西也会有所帮助:索引或字段访问。所以你可以写s[0] = x;(适合类型),但不能写let s[0] = x;
  • 我已经检查了参考,左值现在称为位置表达式。所以答案略有更新。
【解决方案2】:

您缺少let 关键字;它应该是一个变量或一个 let 语句:

let (s3, s4) = take_n_giveback(s3, s4);

【讨论】:

【解决方案3】:
fn main() {
    let s3 = String::from("hello");
    let s4 = String::from("wolrd");

    let (s3, s4) = take_n_giveback(s3, s4);

    println!("{0} and {1}", s3, s4);
}

fn take_n_giveback(x: String, y: String) -> (String, String) {
    (x, y)
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-20
    相关资源
    最近更新 更多