매크로

매크로

매크로는 컴파일 타임에 소스코드를 생성하는 문법이다

반복되는 패턴이나 조건부 컴파일 등에 사용된다.

매크로 이름은 일반적인 식별자 뒤에 !가 붙는다.

사용 방법은 매크로명 뒤에 괄호를붙이고 그 안에 인자를 적는다.

괄호는 소, 중, 대 괄호 어떤것이든 가능하다. 즉, 아래 세 코드는 동일한 일을 한다.

println!("Hello, world!");
println!{"Hello, world!"};
println!["Hello, world!"];

매크로의 성격에 따라 어떤 괄호를 사용할지 관습적으로 정해진다.

일반 러스트 함수와는 다르게 가변 인자를 받을 수 있다.

c언어의 가변인자 함수와의 차이점

가변인자 함수는 인자를 메모리에 저장하고 호출할때마다 하나씩 가져오는 방식이라 타입오류나 인자의 개수가 모자랄 경우 런타임 오류가 발생

매크로는 코드로 변환되서 인자가 몇개인지 타입이 무엇인지 확인하고 실행되기 때문에 컴파일 오류로 잡을 수 있음

선언적 매크로

패턴을 매칭해서, 정해진 템플릿대로 코드를 만들어내는 매크로.

macro_rules!

macro_rules!로 매크로를 정의할 수 있다.

macro_rules! 매크로이름 { // 여기선 매크로이름에 !안 붙임
    (매크로인자 패턴) => { 삽입될 코드 }; // 세미콜론으로 구분
    ...
}

절차적 매크로

코드를 토큰 스트림으로 받아 컴파일러 내부에서 직접 조작해 코드를 만드는 매크로.

  1. 파생 매크로: 구조체나 열거형 위에 #[derive(...)] 형태로 붙여서 해당 타입에 대한 트레이트 구현 코드를 자동으로 생성. 기존의 코드를 변경하지 않고 코드를 추가만 함.
  2. 속성형 매크로: #[macro_name]의 형태로 임의의 항목에 붙여 사용. 파생 매크로와 비슷하지만 구조체뿐만 아니라 함수나 모듈 등 어디에나 붙일 수 있고 원래 있던 코드를 완전히 다른 코드로 덮어써 버릴 수도 있다.
  3. 함수형 매크로: 인수를 주고 호출
    선언적매크로처럼 macro_name!(args, ...)의 형태로 호출하지만 내부로직은 절차적매크로로 동작.