这条奇怪的线是做什么的?
What does this strange line do?
A pull request 已经完成了对 Rust 编译器的新测试。它验证一个奇怪的行可以编译:
fn main() {
let val = !((|(..):(_,_),__@_|__)((&*"\",'@')/**/,{})=={&[..=..][..];})//
;
assert!(!val);
}
这条线到底是做什么的?
让我们分解一下!首先,我重新格式化该行以稍微增加 "readability".
let val = !(
(
|(..): (_, _), __@_| __
)(
(
&*"\",
'@'
) /**/,
{}
)
==
{
&[..=..][..];
}
)//
;
以let val =
开始,以//<newline>;
结束。所以它是 let val = ⟨v⟩;
形式的简单 let-binding。让我们讨论一下 ⟨v⟩
的作用:
- 通过 not 运算符的否定:
!( ⟨_⟩ )
- 通过
==
进行比较:⟨lhs⟩ == ⟨rhs⟩
- ⟨lhs⟩: 闭包函数调用
( ⟨closure⟩ )( ⟨args⟩ )
- ⟨closure⟩:闭包定义
|⟨first_param⟩, ⟨second_param⟩| ⟨body⟩
- ⟨first_param⟩:
(..): (_, _)
。这个参数有一个类型注释 (_, _)
意味着它是一个二元组。模式(通常,您会找到一个名称)是 (..)
,这意味着:一个元组,但忽略它的所有元素。
- ⟨second_param⟩:
__@_
。这是通常从匹配绑定中获知的模式:name @ pattern
。所以实际模式是 _
(不绑定任何东西),值通过 @
绑定到名称 __
(两个下划线,这是一种有效标识符)。
- ⟨body⟩:
__
。这只是我们将第二个参数绑定到的标识符。所以闭包基本等同于|_, x| x
.
- ⟨args⟩:两个参数的列表,中间有一个内联注释
/**/
:⟨first_arg⟩/**/, ⟨second_arg⟩
- ⟨first_arg⟩:
(&*"\", '@')
。这只是一个二元组,其中第一个元素是包含反斜杠的字符串,第二个元素是字符 '@'
。第一个元素的 &*
抵消了。
- ⟨second_arg⟩:
{}
。这是一个类型为 ()
的空块。因此,作为第二个参数,传递了一个单位。
- ⟨rhs⟩:一个花括号块,里面有一个语句:
{ ⟨stmt⟩; }
。请注意,这是一个带有分号的语句。这意味着结果不会从块中返回。相反,块 returns ()
就像空块 {}
一样。
- ⟨stmt⟩:索引表达式
{ &⟨collection⟩[⟨index⟩] }
。
- ⟨collection⟩:
[..=..]
。这是一个只有一个元素的数组。元素是 ..= ..
,它是 RangeToInclusive
where end
of the range is the RangeFull
写成 ..
。
- ⟨index⟩:
..
。这又是 RangeFull
。
所以总而言之:我们将调用闭包的结果与计算结果为 ()
的支撑块进行比较。闭包基本上是 |_, x| x
,我们传递给它的第二个参数是 {}
(计算结果为 ()
),因此整个闭包调用表达式的计算结果为 ()
。
这意味着整个事情等同于:
let val = !( () == () );
,相当于:
let val = !( true );
,相当于:
let val = false;
A pull request 已经完成了对 Rust 编译器的新测试。它验证一个奇怪的行可以编译:
fn main() {
let val = !((|(..):(_,_),__@_|__)((&*"\",'@')/**/,{})=={&[..=..][..];})//
;
assert!(!val);
}
这条线到底是做什么的?
让我们分解一下!首先,我重新格式化该行以稍微增加 "readability".
let val = !(
(
|(..): (_, _), __@_| __
)(
(
&*"\",
'@'
) /**/,
{}
)
==
{
&[..=..][..];
}
)//
;
以let val =
开始,以//<newline>;
结束。所以它是 let val = ⟨v⟩;
形式的简单 let-binding。让我们讨论一下 ⟨v⟩
的作用:
- 通过 not 运算符的否定:
!( ⟨_⟩ )
- 通过
==
进行比较:⟨lhs⟩ == ⟨rhs⟩
- ⟨lhs⟩: 闭包函数调用
( ⟨closure⟩ )( ⟨args⟩ )
- ⟨closure⟩:闭包定义
|⟨first_param⟩, ⟨second_param⟩| ⟨body⟩
- ⟨first_param⟩:
(..): (_, _)
。这个参数有一个类型注释(_, _)
意味着它是一个二元组。模式(通常,您会找到一个名称)是(..)
,这意味着:一个元组,但忽略它的所有元素。 - ⟨second_param⟩:
__@_
。这是通常从匹配绑定中获知的模式:name @ pattern
。所以实际模式是_
(不绑定任何东西),值通过@
绑定到名称__
(两个下划线,这是一种有效标识符)。 - ⟨body⟩:
__
。这只是我们将第二个参数绑定到的标识符。所以闭包基本等同于|_, x| x
.
- ⟨first_param⟩:
- ⟨args⟩:两个参数的列表,中间有一个内联注释
/**/
:⟨first_arg⟩/**/, ⟨second_arg⟩
- ⟨first_arg⟩:
(&*"\", '@')
。这只是一个二元组,其中第一个元素是包含反斜杠的字符串,第二个元素是字符'@'
。第一个元素的&*
抵消了。 - ⟨second_arg⟩:
{}
。这是一个类型为()
的空块。因此,作为第二个参数,传递了一个单位。
- ⟨first_arg⟩:
- ⟨closure⟩:闭包定义
- ⟨rhs⟩:一个花括号块,里面有一个语句:
{ ⟨stmt⟩; }
。请注意,这是一个带有分号的语句。这意味着结果不会从块中返回。相反,块 returns()
就像空块{}
一样。- ⟨stmt⟩:索引表达式
{ &⟨collection⟩[⟨index⟩] }
。- ⟨collection⟩:
[..=..]
。这是一个只有一个元素的数组。元素是..= ..
,它是RangeToInclusive
whereend
of the range is theRangeFull
写成..
。 - ⟨index⟩:
..
。这又是RangeFull
。
- ⟨collection⟩:
- ⟨stmt⟩:索引表达式
- ⟨lhs⟩: 闭包函数调用
- 通过
所以总而言之:我们将调用闭包的结果与计算结果为 ()
的支撑块进行比较。闭包基本上是 |_, x| x
,我们传递给它的第二个参数是 {}
(计算结果为 ()
),因此整个闭包调用表达式的计算结果为 ()
。
这意味着整个事情等同于:
let val = !( () == () );
,相当于:let val = !( true );
,相当于:let val = false;