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 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!