파이썬에는 객체의 생성과 소멸의 범위를 확실하게 정하는 목적으로 with 문법이 존재한다. 파이썬은 C와 달리 블럭 스코프를 이용해서 객체의 생성주기를 통제할수 없기 때문에 with가 존재한다.
with open("x.txt") as f:
data = f.read()
...
C에서는 블럭 스코프가 존재하기 때문에 with statement가 필요없지만 그래도
한번 만들어본 이유는 리눅스 커널의 for_each_process
매크로를 보고
for문을 매크로로 이용해서 확장하는 것이 가능하겠다는 생각을 했기
때문이다.
#define for_each_process(p) \
for (p = &init_task ; (p = next_task(p)) != &init_task ; )
Code
#define WITH_COND_VAR(LINE) __with_run_##LINE
#define WITH_FOR(EXPR, LINE) \
int WITH_COND_VAR(LINE) = false; \
for(EXPR ; WITH_COND_VAR(LINE) == false ; WITH_COND_VAR(LINE) = true)
#define WITH(EXPR) WITH_FOR(EXPR, __LINE__)
for문의 구조를 이용했다. for(...) {}
에서 블럭을 제외한 부분을
매크로로 생성했다. for문이 1번만 돌아가도록 하려면 상태를 저장하는
변수가 필요하다. 이것은 전처리기의 ##
연산자를 이용해서 만들었다. ##
연산자를 이용하면 매크로 토큰을 이어붙일 수 있다.
응용
객체의 생성자와 소멸자를 이용해서 객체가 존재하는 스코프에서의 실행시간을 측정하는 PROFILE 매크로가 있다고 가정하자. 일반적인 C++에서는 다음과 같은 형태로 PROFILE 매크로를 이용한다.
while(!quitGame)
{
{
PROFILE("Poll Joypad");
PollJoypad();
}
{
PROFILE("Game Object Update");
UpdateGameObjects();
}
...
}
WITH 매크로를 이용하면 다음과 같은 식으로 코드를 짤 수 있다.
while(!quitGame)
{
WITH(PROFILE("Poll Joypad"))
{
PollJoypad();
}
WITH(PROFILE("Game Object Update"))
{
UpdateGameObjects();
}
...
}