지난 글에서 이야기 했던 람다(Lambda)의 배경 개념에 대해 알아보겠습니다.
람다 함수는 First-Class Object?
프로그래밍 언어를 이루는 class, struct, int와 같은 개체들 중에서 아래 조건을 만족하면 First-Class Object로 분류합니다. (First-Class Object는 분류의 한 갈래를 의미하는 것이지 상하 관계를 의미하진 않습니다.)
- 변수와 자료구조에 저장하고 사용할 수 있다.
- 함수의 입력 값으로 사용할 수 있다.
- 함수의 반환 값으로 사용할 수 있다.
- 실행 시간에 생성할 수 있다.
즉, 기존 C++에서는 class, struct, int 등이 First-Class Object 였고 아래 예제에서 볼 수 있듯이 C++0x에서 람다 함수(Lambda Function)가 First-Class Object의 조건들을 만족시킵니다.
...
int main()
{
string text = "C++0x Lambda!";
// 1. "코드 조각" 변수에 대입하기
function<void()> lambda = [=]()
{
cout << text << endl;
};
// 2. "코드 조각"을 자료구조에 저장하기
vector< function<void()> > container;
{
container.push_back( lambda );
container.push_back( [=](){ cout << text << endl; } );
};
// 3. "코드 조각"을 함수의 입력 파라미터로 사용하기
for_each( container.begin(), container.end(), [](const function<void()>& f){ f(); } );
return 0;
}
위 조건들을 통해 First-Class Object들은 프로그래밍 언어에서 별 다른 제약 조건 없이 변수로 사용할 수 있게 됩니다. 최근 여러 언어들이 함수를 First-Class Object로 제공하는 이유도 함수를 값 처럼 사용할 수 있게 되면 여러 모로 유용하기 때문입니다. 특히 함수는 다른 First-Class Object들을 생성하거나 조작하는 일련의 코드 묶음이기 때문입니다.
C++0x에서는 람다 함수(Lambda Function)를 First-Class Object로 제공함으로써 코드 조각을 일반 변수처럼 사용할 수 있게 해줍니다.
람다 함수는 Higher-Order Function?
함수의 입력 값으로 함수를 전달 받거나 함수의 결과 값으로 함수를 반환할 수 있을 때 Higher-Order Function이라고 합니다. 아래 예제 코드를 보면 쉽게 알 수 있습니다.
int main()
{
// 1. 람다 함수를 반환 값으로 한다.
auto g = [](int x) -> function<int (int)>
{
return [=](int y) { return x + y; };
};
// 2. 람다 함수를 입력 값으로 받는다.
auto h = [](const function<int (int)>& f, int z)
{
return f(z) + 1;
};
auto a = h( g(7), 8 );
cout << a << endl;
}
예제를 보면 h( g(7), 8 )과 같이 표현된 것을 볼 수 있습니다. 마치 수학 책에서 보던 h( g(x), y )처럼 표현할 수 있는 것입니다. 람다 함수는 C++0x에서 First-Class Object 조건을 만족시키기 때문에 Higher-Order Function의 요구사항 또한 만족시킵니다.
람다 함수는 Closure?
클로저(Closure)는 함수를 호출한 상위 코드 블록의 변수들이 호출된 함수와 묶인 것을 뜻합니다. 즉 호출된 함수는 상위 코드 블록의 외부 변수와 묶여 자기만의 상태를 갖게 되는 것입니다.
C++0x에서는 람다 함수(Lambda Function)가 상위 코드 블록의 변수들과 묶여 클로저(Closure)가 될 수 있다. 이때 람다 함수에서 외부 변수들을 참조하는 것을 ‘캡처’라고 말합니다.
캡처(Capture)는 두 가지 방법으로 할 수 있습니다. 람다 시작을 나타내는 [] 기호 사이에 =과 & 기호를 이용할 수 있습니다. [=]은 값 복사를 의미하고 [&]는 값 참조를 의미합니다. 아래 예제 코드를 보시죠.
…
void capture()
{
int a = 0;
int b = 1;
int c = 2;
// 1. default 값 복사 캡처. 상위 코드 블록의 지역 변수 모두 값 복사 가능
[=](){ cout << a << “ “ << b << endl; }(); // 0 1 출력
// 2. default 값 참조 캡처. 상위 코드 블록의 지역 변수 모두 값 참조 가능
[&](){ cout << a << “ “ << b++ << endl;}(); // 0 1 출력
// 3. default 값 복사 캡처, b와 c 참조 캡처
[=, &b, &c](){ cout << a << “ “ << b << “ ” << c << endl; }(); // 0 2 2 출력
}
…
이번 포스팅에선 몇 가지 배경 개념들을 알아봤는데요, 도움이 되셨는지 모르겠습니다 ;)
다음 글에선 람다 함수의 활용 방안에 대해 알아보겠습니다.
'C++0x' 카테고리의 다른 글
[Plus C++0x] 람다(Lambda) 이야기 (마지막회) (2) | 2010.06.03 |
---|---|
[Plus C++0x] 람다(Lambda) 이야기 (3) (0) | 2010.06.01 |
[Plus C++0x] 람다(Lambda) 이야기 (1) (0) | 2010.05.27 |
"Visual C++ 10과 C++0x" pdf 파일 (4) | 2010.04.20 |
C++0x 관련 책 "Visual C++ 10과 C++0x" (9) | 2010.04.17 |