“|_|”是什么意思 铁锈中的意思是什么?

izz*_*zzy 2 syntax rust

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

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

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

Dai*_*Dai 17

_现在忽略下划线,有必要进行一些说明:

闭包和那些管道字符|

术语“闭包”实际上与“lambda 函数”、“匿名函数”、 “块” 、“内联函数表达式”等术语同义- 它基本上意味着具有环境捕获语义的函数定义,因此闭包可以使用在父作用域中声明的变量。

与任何其他函数一样,闭包需要一个参数列表,Rust 借用了 Ruby使用管道|来表示闭包的参数列表 - 这与 JavaScript 和 C# 等选择使用普通括号的其他流行语言形成鲜明对比用“粗箭头”表示闭包,例如( x, y, z ) =>

Rust 的文档中有一个关于闭包语法的部分,我建议人们阅读。

bigArray例如,下面是语义相似代码的快速比较,这些代码从JavaScript、C#、Ruby 和 Rust 中显示的输入中过滤掉大于或等于 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 )
Run Code Online (Sandbox Code Playgroud)

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.
Run Code Online (Sandbox Code Playgroud)

下划线_

至于下划线:Rust 共享PythonC# 的约定,即使用下划线来表示被丢弃或以其他方式忽略的参数或本地参数。现在你可能想知道被丢弃的参数的意义是什么:为什么不像 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,那么这_是一个方便的解决方案。

的另一个用例_是声明调用站点的返回值被故意丢弃(因此此语法表示intent),例如:

// 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 )
Run Code Online (Sandbox Code Playgroud)

...而如果您只是简单地放在someFunctionThatReturnsAValue();自己的行上,那么其他阅读代码或静态分析工具的人会认为您心不在焉地忘记了检查someFunctionThatReturnsAValue的返回值 - 但 usinglet _ = ...清楚地表明您确实不这样做不关心返回值,这样您就不希望静态分析工具困扰您。


那么给定unwrap_or_else(|_| panic!("Error connecting to {}", database_url)),是什么|_|意思?

  • unwrap_or_else 是 的一种方法std::result

  • unwrap_or_else的参数是一个回调函数op: FnOnce。如果result is-not- Okthenop将被调用,并且op的返回值成为表达式的最终结果unwrap_or_else(或者它会引起恐慌......你的调用)。

    • 至关重要的是,op中的函数unwrap_or_else接受一 (1) 个参数,该参数是E中包含的错误值result
    • 在这种情况下,panic!("Error connecting to {}", database_url))表达式根本不使用内部错误值(我认为这是一个坏主意),因此回调闭包/函数使用语法丢弃该值_
  • 所以总而言之|_|in的unwrap_or_else(|_| panic!("Error")意思是“ 的参数unwrap_or_else是一个接受E(错误值)类型参数的匿名函数 - 但我们只是不关心它,所以假装它不存在”

  • 除了你提到的两种语言之外,“而不是像其他人一样墨守成规并使用 ( ) =&gt; ”,我想不出任何其他编程语言使用 `() =&gt;` 来表示 lambda。Haskell 有 `\ -&gt;`,OCaml 有 `fun` 或 `function`,Python 有 `lambda :`,scheme 有 `(lambda () )`,Ruby 有类似的管道语法,C++ 有 `[](){ }`, ... (5认同)
  • @BlackBeans Rust 的管道语法确实取自 Ruby (https://doc.rust-lang.org/stable/reference/influences.html)。 (2认同)