针对Rust编译器,一份新的测试已被提交pull request。它验证了一个奇怪的代码可以通过编译:
fn main() {
let val = !((|(..):(_,_),__@_|__)((&*"\\",'@')/**/,{})=={&[..=..][..];})//
;
assert!(!val);
}
这行代码到底是做什么的?
针对Rust编译器,一份新的测试已被提交pull request。它验证了一个奇怪的代码可以通过编译:
fn main() {
let val = !((|(..):(_,_),__@_|__)((&*"\\",'@')/**/,{})=={&[..=..][..];})//
;
assert!(!val);
}
这行代码到底是做什么的?
让我们来分解一下!首先,我重新格式化了这行代码,以提高可读性。
let val = !(
(
|(..): (_, _), __@_| __
)(
(
&*"\\",
'@'
) /**/,
{}
)
==
{
&[..=..][..];
}
)//
;
这段代码以let val =
开头,以//<newline>;
结尾。因此,它是一个简单的let绑定形式,即let val = ⟨v⟩;
。让我们讨论一下⟨v⟩
代表什么:
!( ⟨_⟩ )
==
比较: ⟨lhs⟩ == ⟨rhs⟩
( ⟨closure⟩ )( ⟨args⟩ )
|⟨first_param⟩, ⟨second_param⟩| ⟨body⟩
(..): (_, _)
。此参数有一个类型注释(_, _)
,表示它是一个2元组。模式(通常在其中找到单个名称)为(..)
,这意味着:一个元组,但忽略其所有元素。__@_
。这是通常从匹配绑定中知道的模式:name @ pattern
。因此实际模式是_
(不绑定任何内容),并且通过@
绑定值到名称__
(两个下划线,这是一种有效的标识符)。__
。这只是我们将第二个参数绑定到的标识符。因此,该闭包基本上等同于|_, x| x
。/**/
:⟨first_arg⟩/**/, ⟨second_arg⟩
(&*"\\", '@')
。这只是一个2元组,其中第一个元素是包含反斜杠的字符串,第二个元素是字符'@'
。第一个元素的&*
被取消了。{}
。这是一个空块,其类型为()
。因此,作为第二个参数,传递了一个单元。{ ⟨stmt⟩; }
。请注意,这是一个带有分号的语句。这意味着结果不是从块返回的。相反,该块返回()
,就像空块{}
一样。
{ &⟨collection⟩[⟨index⟩] }
。
[..=..]
。这是一个带有一个元素的数组。该元素是RangeToInclusive
,其中范围的end
为RangeFull
,写为..
。..
。这只是RangeFull
。因此总结一下:我们将调用闭包的结果与评估为()
的大括号块进行比较。 闭包基本上是|_, x| x
,我们传递给它的第二个参数是{}
(它评估为()
),因此整个闭包调用表达式评估为()
。
这意味着整个过程等同于:
let val = !( () == () );
,相当于:let val = !( true );
,相当于:let val = false;
weird-exprs.rs
文件,其中函数名称像zombiejesus
和evil_lincoln
这样奇怪。 - Lukas Kalbertodt