使用Rust编译器的新测试完成pull request。它验证了一个奇怪的行可以编译:
fn main() {
let val = !((|(..):(_,_),__@_|__)((&*"\\",'@')/**/,{})=={&[..=..][..];})//
;
assert!(!val);
}
这条线到底是做什么的?
答案 0 :(得分:23)
让我们分解吧!首先,我重新格式化了这条线,以增加“可读性”。
let val = !(
(
|(..): (_, _), __@_| __
)(
(
&*"\\",
'@'
) /**/,
{}
)
==
{
&[..=..][..];
}
)//
;
以let val =
开头,以//<newline>;
结尾。因此,它是let val = ⟨v⟩;
形式的简单let-binding。我们来讨论一下⟨v⟩
的作用:
!( ⟨_⟩ )
==
进行比较:⟨lhs⟩ == ⟨rhs⟩
( ⟨closure⟩ )( ⟨args⟩ )
的函数调用
|⟨first_param⟩, ⟨second_param⟩| ⟨body⟩
(..): (_, _)
。此参数具有类型注释(_, _)
,这意味着它是一个2元组。模式(通常情况下,您会找到一个名称)是(..)
,这意味着:一个元组,但忽略它的所有元素。__@_
。这是一种通常从匹配绑定中获知的模式:name @ pattern
。所以实际模式是_
(它不绑定任何东西),并且值通过@
绑定到名称__
(两个下划线,这是一种有效的标识符)。 __
。这只是我们将第二个参数绑定到的标识符。因此,闭包基本上等同于|_, x| x
。/**/
:⟨first_arg⟩/**/, ⟨second_arg⟩
(&*"\\", '@')
。这只是一个2元组,其中第一个元素是包含反斜杠的字符串,第二个元素是char '@'
。第一个元素的&*
取消。{}
。这是一个类型为()
的空块。所以作为第二个论点,一个单位被传递。{ ⟨stmt⟩; }
。请注意,这是一个带分号的语句。这意味着结果不会从块返回。相反,该块返回()
,就像空块{}
一样。
{ &⟨collection⟩[⟨index⟩] }
。
[..=..]
。这是一个包含一个元素的数组。元素为..= ..
,其为RangeToInclusive
,其中end
范围为RangeFull
..
。 ..
。这只是RangeFull
了。 总结:我们将调用闭包的结果与计算结果为()
的支撑块进行比较。闭包基本上是|_, x| x
,我们传递给它的第二个参数是{}
(计算结果为()
),因此整个闭包调用表达式的计算结果为()
。
这意味着整个事情等同于:
let val = !( () == () );
,相当于:let val = !( true );
,相当于:let val = false;
强>