A pull request已经完成了对 Rust 编译器的新测试。它验证一个奇怪的行是否可以编译:
fn main() {
let val = !((|(..):(_,_),__@_|__)((&*"\\",'@')/**/,{})=={&[..=..][..];})//
;
assert!(!val);
}
这条线到底做了什么?
最佳答案
让我们分解一下!首先,我重新格式化了该行以增加“可读性”。
let val = !(
(
|(..): (_, _), __@_| __
)(
(
&*"\\",
'@'
) /**/,
{}
)
==
{
&[..=..][..];
}
)//
;
以let val =
开头并以 //<newline>;
结尾.所以这是一个简单的 let-binding 形式 let val = ⟨v⟩;
.让我们讨论一下⟨v⟩
做:
- 通过not 运算符的否定:
!( ⟨_⟩ )
- 通过
==
进行比较:⟨lhs⟩ == ⟨rhs⟩
- ⟨lhs⟩:闭包的函数调用
( ⟨closure⟩ )( ⟨args⟩ )
- ⟨closure⟩:闭包定义
|⟨first_param⟩, ⟨second_param⟩| ⟨body⟩
- ⟨first_param⟩:
(..): (_, _)
.此参数具有类型注释(_, _)
这意味着它是一个二元组。模式(通常情况下,您会找到一个名称)是(..)
这意味着:一个元组,但忽略它的所有元素。 - ⟨second_param⟩:
__@_
.这是通常从匹配绑定(bind)中获知的模式:name @ pattern
.所以实际模式是_
(不绑定(bind)任何东西)并且值通过@
绑定(bind)到名字__
(两个下划线,是一种有效的标识符)。 - ⟨body⟩:
__
.这只是我们将第二个参数绑定(bind)到的标识符。所以闭包基本上等同于|_, x| x
.
- ⟨first_param⟩:
- ⟨args⟩:带有内联注释的两个参数的列表
/**/
介于两者之间:⟨first_arg⟩/**/, ⟨second_arg⟩
- ⟨first_arg⟩:
(&*"\\", '@')
.这只是一个二元组,其中第一个元素是包含反斜杠的字符串,第二个元素是字符'@'
。 .&*
对于第一个元素抵消。 - ⟨second_arg⟩:
{}
.这是一个类型为()
的空 block .因此,作为第二个参数,传递了一个单位。
- ⟨first_arg⟩:
- ⟨closure⟩:闭包定义
- ⟨rhs⟩:一个包含一个语句的大括号 block :
{ ⟨stmt⟩; }
.请注意,这是一个带有分号的语句。这意味着结果不会从 block 中返回。相反,该 block 返回()
就像空 block{}
.- ⟨stmt⟩:索引表达式
{ &⟨collection⟩[⟨index⟩] }
.- ⟨收藏⟩:
[..=..]
.这是一个只有一个元素的数组。元素是..= ..
这是一个RangeToInclusive
其中end
范围的是RangeFull
写..
. - ⟨index⟩:
..
.这只是RangeFull
再次。
- ⟨收藏⟩:
- ⟨stmt⟩:索引表达式
- ⟨lhs⟩:闭包的函数调用
- 通过
总结:我们将调用闭包的结果与计算结果为 ()
的花括号 block 进行比较.闭包基本上是 |_, x| x
我们传递给它的第二个参数是 {}
(计算结果为 ()
),因此整个闭包调用表达式的计算结果为 ()
.
这意味着整个事情等同于:
-
let val = !( () == () );
,相当于: -
let val = !( true );
,相当于: -
let val = false;
关于rust - 这条奇怪的线是做什么的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50717243/