rust-quiz:001-macro-count-statements.rs
题目
macro_rules! m {
($($s:stmt)*) => {
$(
{ stringify!($s); 1 }
)<<*
};
}
fn main() {
print!(
"{}{}{}",
m! { return || true },
m! { (return) || true },
m! { {return} || true },
);
}
关键
statement
首先,要搞清楚语句声明的的边界是什么。
多数情况下,当然是以;
作为结尾,但是不应该忽略的还有一些特殊域
符号
()
:优先求值{}
:特殊声明边界
return
这里包含两个意思,统一的概念叫做返回值
。
- 使用
return
可以进行方法的中断,直接进行值返回。 - 没有特殊声明,
{}
域内最后一个表达式求值作为返回值 ;
后返回的是()
单元类型
||
双重场景
- 无参闭包
- 真值
or
<<
左移符号,n << 1相当于 n \times 2
!
or never
一般用于匹配特殊分支,标识永不返回
。
特性之一是匹配任意类型。
*
在macro_rules
定义的宏里面,多项展开中需要定一个展开式:$()
。
内部的*
代表可省略,前提是是最后一个,否则多个展开之间还是会加上可省略符号。
解题
展开
$(
{ stringify!($s); 1 }
)<<*
首先,传入的多个语句,每一项展开的结果显而易见,{ stringify!($s); 1 }
。
如果是多个语句,语句之间还会加上<<
。
最后打印是有返回值的,也就是说,我们还需要对{ stringify!($s); 1 }
进行求值。
不难看出,实际的值就是最后的1
。
所以,我们最后的结果应该类似于1<<1<<1...
。1
的个数,对于传入语句的个数n
,换算之后返回的值应该是2 ^ {n-1}。
因此,最后的结果就转换为了判断传入的语句的个数。
判断
return || true
这里应该拆分为return (|| true)
,不难看出,|| true
是一个无参闭包。
因此这里返回的应该是1
,整体就是一个语句。(return) || true
这里,因为|| true
丢失了return
的作用,实际上变成了两个bool
的||
。
因为类型匹配,这里(return)
返回的是!
,也就是never
类型。
整体就是一个or
运算,因此语句数量还是1
。{return} || true
这里需要想起的区分()
和{}
的区别。()
:标识优先求值,但是不和整体的运算脱离{}
:自成一域,切断与其他计算的关联
因此,这里实际上是一个语句声明{return}
,之后返回一个无参闭包|| true
。
也就是说这里有两个语句,应该返回的是2
。
答案
综上所述,返回的结果应该是112
。
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: