Rust 매크로(Macro) 활용하기
매크로
- attributes
# [ $arg ]: e.g.#[derive(Clone)],#[no_mangle]# ! [ $arg ]: e.g.#![allow(dead_code)],#![crate_name="blang"]
- function-like
$name ! $arg: e.g.println!("Hi!"),vec![1, 2, 3]
- 선언할 수 없는 매크로
$name ! $arg0 $arg1:macro_rules! dummy { () => {}; }
Function-like 매크로
Expansion
매크로를 선언하고 사용하면 어떻게 확장되어 실행되는지에 대한 예시입니다.
#[macro_export]
macro_rules! vec {
( $( $x:expr ), * ) => {
{
let mut temp_vec = Vec::new();
$(
temp_vec.push($x);
)*
temp_vec
}
}
}
let v = vec![1, 2, 3];
let v = {
let mut temp_vec = Vec::new();
temp_vec.push(1);
temp_vec.push(2);
temp_vec.push(3);
temp_vec
};
Matching
macro_rules! $name {
($matcher) => {$expansion};
($matcher) => {$expansion};
// …
($matcher) => {$expansion};
}
- 적어도 하나 이상의 룰을 선언해야 합니다.
- 마지막 룰에는
;을 생략할 수 있습니다.
Metavariables
matcher는 capture를 포함할 수 있습니다. capture는 $<identifier>:<fragmentSpecifier>로 구성됩니다. fragment-specifier는 다음과 같습니다.
blockexpridentitemlifetimeliteralmetapat: patternpat_parampathstmttt: token treety: typevis: visibility qualifier
Repetition
반복은 $ ( ... ) <separator> <repeatOperator>로 표현됩니다.
<separator>- 선택사항입니다.
- e.g.
,,;
<repeatOperator>?: 0 또는 1 개*: 0 개 이상+: 1 개 이상
macro_rules! vec {
( $( $x:expr ), * ) => {
{
let mut temp_vec = Vec::new();
$(
temp_vec.push($x);
)*
temp_vec
}
}
}