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는 다음과 같습니다.
block
expr
ident
item
lifetime
literal
meta
pat
: patternpat_param
path
stmt
tt
: 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
}
}
}