rust 什么"|_|"在拉斯特是什么意思?

35g0bw71  于 2023-02-23  发布在  其他
关注(0)|答案(1)|浏览(211)

我正在学习如何连接数据库到 rust 程序。有一些我不太明白:

PgConnection::establish(&database_url).unwrap_or_else(|_| panic!("Error connecting to {}", database_url))

这个表达式是什么意思?|_|是什么意思?

2vuwiymt

2vuwiymt1#

现在忽略下划线_,一些解释是必要的:

密封件和管道字符|

术语“闭包”实际上与“lambda函数”、“匿名函数”、"block"、“内联函数表达式”等术语同义--它基本上表示具有 * 环境捕获 * 语义的函数定义,因此闭包可以使用父作用域中声明的变量。
闭包,像其他函数一样,需要一个参数列表,Rust borrowed Rubyuse of pipes |表示闭包的参数列表--这与其他流行的语言如JavaScript和C#相反,后者选择使用带有“* 胖箭头 *”的普通括号来表示闭包,例如( x, y, z ) =>
我推荐人们阅读的Rust's documentation has a section on their syntax for closures
例如,下面是一个语义相似的代码的快速比较,这些代码从JavaScript、C#、Ruby和Rust中显示的输入bigArray中过滤掉大于或等于5的数字:

// JavaScript:
const smallerArray = bigArray.filter( ( num ) => num < 5 );

// C#:
Int32[] smallerArray = bigArray.Where( num => num < 5 ).ToArray();
Int32[] smallerArray = bigArray.Where( ( Int32 num ) => num < 5 ).ToArray(); // With parameter-list parentheses and explicit parameter types.

// Ruby:
smallerArray = bigArray.select {|num| num < 5}

// Rust:
let smaller_array = big_array.into_iter().filter( |num| num < 5 )

Rust和JavaScript一样,C#和Ruby也支持多语句闭包--上面的4个例子都是单参数、单表达式闭包,而等价的多语句体闭包则稍微扩展了语法:

// JavaScript:
const smallerArray = bigArray.filter( ( num ) => { return num < 5; } );

// C#:
Int32[] smallerArray = bigArray.Where( ( Int32 num ) => { return num < 5; } ).ToArray(); // You can also use the *very-old* `delegate( Int32 num ) { ... }` syntax.

// Ruby:
smallerArray = bigArray.select do |num|
    num < 5
end

// Rust:
let smaller_array = big_array.into_iter().filter( |num| { num < 5 } ); // Rust does not require a `return` statement here.

下划线_

至于下划线:Rust共享Python'sC#'s的约定,即使用下划线来表示一个 * disposed * 或忽略的参数或局部变量,现在你可能想知道一个disposed参数的意义是什么:为什么不像在JavaScript中那样完全忽略它呢?(例如,bigArray.filter( x => x < 5 )bigArray.filter( ( x, idx ) => x < 5 )bigArray.filter( ( x, idx, arr ) => x < 5 )都是等效的。
... JavaScript不支持函数重载:每个函数名解析为一个单独的函数实现,所以省略未使用的参数不是问题。现在,虽然Rust也不支持函数重载,但它仍然是一个非常庞大和复杂的语言,在许多情况下,您需要显式声明一个您不使用的参数(严格地说,_表示未绑定的标识符,不能将_用作变量)。
在Rust中,将函数参数命名为_的主要用例是因为它是一个用“must_use“属性注解的值--但是如果你 * 真的知道 * 你不需要使用那个(绑定的)参数,并且你不想被关于must_use值的低值编译器警告轰炸,那么_是一个方便的解决方案。
_的另一个用例是声明调用点的返回值被 * 故意 * 丢弃(因此这个语法 * 表示意图 *),例如:

let _ = someFunctionThatReturnsAValue();

......然而,如果你只是简单地将someFunctionThatReturnsAValue();放在它自己的行上,那么任何其他阅读代码的人,或者静态分析工具,都会认为你心不在焉地忘记检查someFunctionThatReturnsAValue的返回值--但是使用let _ = ...可以清楚地表明,* 你真的不关心 * 返回值,所以你不希望静态分析工具给你带来麻烦。
那么给定unwrap_or_else(|_| panic!("Error connecting to {}", database_url))|_|意味着什么?

  • unwrap_or_elsestd::result的一种方法。
  • unwrap_or_else的参数是一个回调函数op: FnOnce。如果result不是Ok,那么op将被调用,并且op的返回值将成为unwrap_or_else表达式的最终结果(或者它会死机......您的调用)。
  • 至关重要的是,unwrap_or_else中的op函数接受一(1)个参数,即result中包含的E错误值。
  • 在这种情况下,panic!("Error connecting to {}", database_url))表达式根本不使用内部错误值(我认为这是一个坏主意),因此回调闭包/函数使用_语法丢弃该值。
  • 所以在结论中|_|unwrap_or_else(|_| panic!("Error")中意味着 unwrap_or_else的参数是一个匿名函数,接受一个E(错误值)类型的参数--但是我们不关心它,所以假装它不存在”

相关问题