折叠 Rust 匹配

Collapse Rust Matching

我是 Rust 新手,缺少 Swift 中的 if letguard let 符号。

我有以下代码块:

fn some_function() -> Option<String> {
  let client = reqwest::Client::new();

  // res is normally a response type. I've mapped it to an Option type to drop the error
  let res = client
    .post(&complete_path)
    .basic_auth(self.username.clone(), Some(self.password.clone()))
      .send()
      .ok();

  // Verify status code and exist if res = None, or status !== 200
  let mut response = match res {
    Some(res) => match res.status() {
      StatusCode::OK => res,
      _ => return None
    },
    _ => return None
  };

  // Attempt to read the body contents
  let token = match response.text() {
    Ok(data) => Some(data),
    Err(_e) => None
  };

  token
}

在 swift 我会写这样的东西:

guard let response = response,
  response.status == 200
  let text = response.text() else {
  return None
}
return text

我是否遗漏了一些 shorthand 符号?

我正在尝试利用 return 从任何地方使用 return 的能力来缩短某些执行,但它仍然比我熟悉的要冗长得多。


编辑:

我可以使用 match + 子句语法来折叠一些 rust,如下所示:

let mut response = match res {
  Some(res) if res.status() == StatusCode::OK => res,
  _ => return None
}

比原来的好多了。

If let 也可以,但是这里 if let 的问题是我正在查看这里的失败路径。我不想窝在幸福的路上。

有人提议制作更灵活的等价物(守卫,if let … && …),但在这种情况下,由于您通过返回 None 退出,您可以使用 the question mark operator

fn some_function() -> Option<String> {
  let client = reqwest::Client::new();

  let res = client
    .post(&complete_path)
    .basic_auth(self.username.clone(), Some(self.password.clone()))
      .send()
      .ok()?;

  if res.status() != StatusCode::OK {
    return None;
  }

  response.text().ok()
}

考虑同时返回一个 Result<String, …>Box<dyn Error>?),这可能更干净 API 并且可以让您跳过 .ok().