매크로
매크로 (Macros)
반복되는 문법을 줄이고 싶거나, 언어 자체의 기능을 확장하고 싶을 때 Rust의 매크로가 쓰입니다. 이름을 붙여 두고 some_extension!(...)처럼 일관된 문법으로 호출한다는 점이 핵심인데요, 이 문서에서 매크로의 정의 방식과 호출 규칙을 정리해 볼게요.
출처: Rust Reference
Rust의 기능과 문법은 매크로라고 부르는 사용자 정의로 확장할 수 있습니다. 매크로는 이름을 가지며, some_extension!(...)이라는 일관된 문법으로 호출돼요.
새 매크로를 정의하는 방법은 두 가지입니다:
- Macros by Example은 새로운 문법을 보다 선언적이고 상위 수준(high-level)으로 정의합니다.
- Procedural Macros은 입력 토큰에 대해 동작하는 함수를 이용해 함수형 매크로, 커스텀 derive, 커스텀 속성을 정의합니다.
매크로 호출 (Macro Invocation)
문법 (Syntax)
MacroInvocation → SimplePath ! DelimTokenTree
DelimTokenTree → ( TokenTree* ) | [ TokenTree* ] | { TokenTree* }
TokenTree → Token(구분자 제외) | DelimTokenTree
MacroInvocationSemi →
SimplePath ! ( TokenTree* ) ;
| SimplePath ! [ TokenTree* ] ;
| SimplePath ! { TokenTree* }
매크로 호출은 컴파일 타임에 매크로를 확장하고, 그 호출을 매크로의 결과로 치환합니다. 매크로는 다음 상황에서 호출될 수 있어요:
- 표현식과 문(statement)
- 패턴
- 타입
- 아이템 — 연관 아이템 포함
macro_rules트랜스크라이버- 외부 블록
아이템이나 문으로 사용할 때는 MacroInvocationSemi 형식을 쓰는데, 중괄호를 쓰지 않는다면 끝에 세미콜론이 필요합니다. 가시성 한정자(visibility qualifier)는 매크로 호출이나 macro_rules 정의 앞에 절대 올 수 없어요.
#![allow(unused)]
fn main() {
// Used as an expression.
let x = vec![1,2,3];
// Used as a statement.
println!("Hello!");
// Used in a pattern.
macro_rules! pat {
($i:ident) => (Some($i))
}
if let pat!(x) = Some(1) {
assert_eq!(x, 1);
}
// Used in a type.
macro_rules! Tuple {
{ $A:ty, $B:ty } => { ($A, $B) };
}
type N2 = Tuple!(i32, i32);
// Used as an item.
use std::cell::RefCell;
thread_local!(static FOO: RefCell<u32> = RefCell::new(1));
// Used as an associated item.
macro_rules! const_maker {
($t:ty, $v:tt) => { const CONST: $t = $v; };
}
trait T {
const_maker!{i32, 7}
}
// Macro calls within macros.
macro_rules! example {
() => { println!("Macro call in a macro!") };
}
// Outer macro `example` is expanded, then inner macro `println` is expanded.
example!();
}
위 코드에서 보듯 매크로는 표현식·문·패턴·타입·아이템·연관 아이템 어디서든 호출될 수 있고, 매크로 안에서 다른 매크로를 호출하는 것도 가능해요. example!()은 먼저 바깥 매크로 example이 확장된 뒤, 그 안의 println 매크로가 확장됩니다.
매크로 호출은 두 종류의 스코프로 해석됩니다:
- 텍스트 스코프 (Textual Scope) — 텍스트 스코프의
macro_rules - 경로 기반 스코프 (Path-based Scope) — 경로 기반 스코프의
macro_rules, Procedural macros
더 알아보기 (Learn more)
- Macros by Example —
macro_rules!선언적 매크로 - Procedural Macros — 함수형 매크로·커스텀 derive·커스텀 속성
- 경로 (Paths) — 매크로 경로 기반 스코프
- 토큰 (Tokens) — 토큰 트리 정의