정말 오랜만에 나머지 번역하고 있습니다. 언제쯤 끝날지...-__-;;;


Bjarne Stroustrup Concept와 미래를 말하다 - 1  http://jacking.tistory.com/443

Bjarne Stroustrup Concept와 미래를 말하다 - 2  http://jacking.tistory.com/467

Bjarne Stroustrup Concept와 미래를 말하다 - 3  http://jacking.tistory.com/474

Bjarne Stroustrup Concept와 미래를 말하다 – 4 http://jacking.tistory.com/559


 


Danny Kalev

저는 그다지 Concept의 팬이 아닙니다만 conceptrequires 키워드의 필요성은 알고 있습니다.

그래도 왜 concept map이나 axiom 등이 필요합니까? 개인적으로는 언어를 무의미하게 복잡화 시키고 탁상 공론으로 비 현실적인 장난감이라고 생각합니다. 도움이 되는 이용 방법도 있겠지만 처음은 기본적인 곳부터 시작하여 나중에 주의 깊게 확장해 가는 것이 좋지 않을까요?

 

 

Bjarne stroustrup

.. ~. 키워드 수의 삭감이 목적은 아닙니다. 제네릭 프로그래밍을 지원하기 위해서 필요합니다. concept을 편리하게 하려면 현행의 성공 예를 명확화 해서 지원하지 않으면 안됩니다. concept이 받아 들여지기 위해서는 현행의 성공 예를 완전하게 지원하지 않으면 안됩니다. 그렇지 않으면constrainedunconstrained template가 뒤죽박죽 될 뿐입니다. concept이 받아 들여지기 위해서는 「구태 의연한 unconstrainedtemplate로부터 「concept baseconstrainedtemplate로의 간단한 변환 방법을 제공하지 않으면 안됩니다. 이야기는 빗나가지만 제가 프랑크푸르트 전의 컨셉 규격의 설계에 대한 usability에의 염려는 이것도 관계하고 있습니다.

 

concept map에 대해서 생각해 보죠. concept에 임의의 형태를 적용시키는 어떠한 기구가 필요합니다. 이 기능이 없으면 그 concept을 염두로 설계된 형태만 사용할 수 있습니다. 당신이 행운의 별에서 태어났다면 우연히 시그너쳐가 일치하고 있을지도 모르겠네요. 원래 완전한 신기능이기 때문에 유저끼리 서로 협조하면 concept에 일치하는 형태를 강제할 수 있을 것이라고 생각할지도 모릅니다. 그런데 C++라고 하는 것은 1972년부터의 역사를 가지고 있고 넓게 사용되고 있는 언어입니다. 이미 많은 상상도 할 수 없는 듯한 형태가 있고, 매일 매일 새로운 형태나 concept이 만들어지고 있습니다.

 

잠시 여기서 말해 둘 것이 최근 10년 정도부터 개발자들은 이미 concept을 발명하였고 템플릿을 그 concept에 따라서 쓰고 있습니다. 그러한 「concept」은 단지 명시화 되어 있지 않은 정도 입니다. 대체로 필요 사항 등 문서도 불완전하고 제멋대로인 가정도 포함되어 있습니다.

 

그러한 이유로 기존의 concept 예를 들면 random access iterator와 기존의 형태 예를 들면 int*를 예로 들겠습니다. 여기서 형태를 concept을 요구하는 템플릿 인수로 사용하고 싶다고 합니다. 도대체 어떻게 하면 좋을까요? 언어에 concept map이 없으면 꾸며낼 수 밖에 없습니다. 예를 들면 RandomAccessIterator는 멤버형(역주:규격적으로 말하면 클래스에 네스트 된 형태)으로서value_type이 없으면 안됩니다. RandomAceessIterator를 사용하는 템플릿 코드는 그 이름을 인수의 형태의 멤버 명으로서 사용합니다. 그런데 int*에는 value_type 등이라고 하는 멤버는 없습니다. 원래 int*에는 멤버 따위가 없습니다. 그렇다고 하는 것은 Dennis Ritche가 포인터에 멤버 등이 필요 없다고 1972년에 결정했기 때문입니다. 타임 머신도 있지 않는한 당시 int*에 멤버를 덧붙이는 것은 할 수 없고, 그 때문에 C with value_type(역주:C with classes의 패러디)등이라고 하는 언어를 1994년 시점에서 발명하는 것도 할 수 없었던 것입니다.

 

언어에 concept map이 없으면 자신이 map을 만들 수 밖에 없습니다. 이 「map」은 int*의 래퍼 클래스로 value_type을 멤버로 가지고 있으며 다른 random access 조작도 할 수 있습니다. 행운과 뛰어난 컴파일러를 타고 나면 int*와 정말 변함 없는 성능을 얻을 수 있을 것입니다. 그리고는 모든 int*Self 클래스의 RandomAccessIterator로 래핑 할 뿐입니다. 제네릭 프로그래밍의 경험이 있으면 이런 류의 래퍼 클래스나 비슷한 아이디어인 traits는 자주 보았을 것입니다. 이러한 workaround 코드는 일반적이고 제네릭 코드에서는 간단합니다. 다만 쓰는 것은 귀찮고 대체로는 범용적이지 않고 극히 한정된 것 밖에 동작하지 않습니다. 전문가가 아니면 이해 하기 어렵습니다. 그래서 문제의 원인입니다.

concept_map은 이러한 현실적이고 근본적인 문제의 직접적인 해결 방법입니다. 예를 들면

 

template<class T> concept_map RandomAccessIterator<T*> {

typedef T value_type;

};

 

이것은 T* RandomAccessIterator로서 사용하면 그 value_typeT라고 하는 의미입니다. 위와 같이 어떤 문법이 제일 좋은 것인가에 대해서는 논의가 있지만 이러한 것을 표현할 필요가 있습니다. 「이러한 것을 표현」하는 것은 실제로 필요합니다. 완벽하고 범용적인 workaround 등이 존재하지 않습니다. 그러니까 언어 기능으로서 반드시 필요합니다. concept map 없이 concept을 사용한 제네릭 코드 등을 쓰고 싶다고는 생각하지 않습니다.

 

simplifying the use of concepts에서의 논의를 또 언급 하지 않겠지만 제가 말하고 싶었던 것은 concept map은 쓸데 없이 너무 사용되고 복잡하고 사용하기 어렵다고 하는 것입니다. 저는 그 문제를 해결하기 위한 제안을 했습니다. 무엇이든 존재하지 않는 조작을 덧붙이거나 이름을 바꾸거나 하여 형태를 concept에 일치시키기 위한 구조로서 concept map은 경험상 필요하고 논의의 여지도 없는 것입니다.

 

이미 설명한 것처럼 concept는 지정된 문법에 대해서 동작합니다. 어느 형태가 구체적인 이름에 의한 조작이나 형태를 가지고 있지 않으면 안 된다고 하는 것을 명시합니다. 예를 들면 random access iterator로서 사용하기 위해서는 그 형태는 *, ++, [], value_type 등을 제공하고 있지 않으면 안 되는 것 등입니다. 상식적으로 생각하면 이러한 조작은 「올바른 일을 한다」라고 보여지고 있으며 그 「올바른 일」은 어딘가 다른 문서에 쓰여져 있습니다. 이 경우 C++ 표준 규격입니다. 이것은 concept이 언어 측에서 지원 되고 있는지 어떤지에 관련되지 않고 하나입니다. 템플릿에 대한 문서라고 하는 것은 의미적인 필요 사항을 모두 쓴 것입니다. 좋은 문서일수록 그 필요 사항도 자세하게 쓰여지게 됩니다. 여기서의 문제란 도대체 어디까지 의미적인 필요 사항을 언어 측에서 지원하면 좋은 것인가? 또 어떻게 지원하는 것인가? 라고 하는 것입니다.

 

axiom에서는 코드 중에 자세한 의미 상의 규약을 간단한 문법으로 기술할 수 있습니다. 예를 들면

 

concept ForwardIterator<typename X> : InputIterator<X>, Regular<X> {

  requires Convertible<postincrement_result, const X&>;

  axiom MultiPass(X a, X b) {

   if (a == b) *a <=> *b;

   if (a == b) ++a <=> ++b;

  }

}

 

이 기술은 ForwardIterator이란 InputIterator이며 == 등을 제공하여 Regular이며 시퀀스에 대해서multiple pass라고 하는 공리가 성립됩니다. <=>라는 것은 동등 연산자입니다. ForwardIteratorab에 대해서 ab가 동일하다면 *a에 대한 조작은 *b에 대한 조작과 동일하다 입니다. 고등학교의 대수학에 약한 녀석들은 맨발로 도망갈 것입니다. 그러나 기술된 논리라고 하는 것은 고전적으로 범용적이고 의미를 기술하는데 효과적입니다.

 

axiom의 규격 설계에는 두 개의 목적이 있습니다.

l  보다 자세한 문서를 기술시키는 것.

l  프로그래머는 코드 상에서 직접 개발 환경에 정보를 전할 수 있는 것.

 

많은 무리는 axiom의 목적을 아래와 같이 잘못 생각하고 있습니다.

 

l  axiom은 컴파일러에 의해 좋은 코드를 생성시키기 위한 것이라는 등.
실제 axiom는 특히 그러한 용도가 뛰어나지 않습니다. 제가 사용하는 형태라고 하는 것은 수학적인 법칙에 따르는 것은 아니기 때문입니다. double과 같은 부동 소수점수(실수)는 실수의 법칙에는 따르지 않습니다. 실수에는 NaN 등이 없기 때문입니다. int의 종류는 정수의 법칙에는 따르지 않습니다. 수학적인 정수는 오버플로우 등이 없습니다. 만약 axiom을 최적화를 위해 설계하고 있었다면 지금쯤 대 실패했을 것입니다.

 

l  axiom은 형태를 증명하기 위한 것이 라는 등등.
수학을 공부할 때 공리라고 하는 것은 증명을 하기 위해서 사용하는 것입니다. 저도 C++ 컴파일러에 정리의 증명 기능 따위를 제안할 생각은 없습니다.

 

l  제안되고 있는 술어 이론(역주:predicate logic)의 문법으로 충분히 의미 기술을 할 수 있는 것인가? 더 확장해서는 안 되는 것인가? 등등.
술어 이론은 매우 길고 또 훌륭한 역사를 자랑하고 있으며 표현력이 있습니다. 저는 모험적으로 확장하거나 하지 않습니다.

 

라는 것은 axiom의 사용 목적과 자주 있는 오해를 설명한 것입니다. 그럼 남은 이용 방법은 도움이 되는가 하면 도움이 된다고 말할 수 있습니다. concept의 문서에는 많은 공리를 이용하고 있다고 하는 현실이 있습니다. 그러나 이점이라고 하는 것은 실제로 나타내 보이는 것이 어렵습니다.

여기서 axiom의 구체적인 사용법을 설명 하거나 하지 않지만(자세한 것은 N2887 참조)concept을 사용하는데 있어서의 어려운 문제에 문법상은 거의 같지만 의미가 다른 복수의concept이라고 하는 것이 있습니다. 예를 들어 foward iteratorinput iterator입니다. 저는 다음의 concept의 설계에서는 더 axiom을 전면적으로 밀어 내고 의미상의 차이를 취급하기 쉽게 할 생각입니다.

 


by 흥배 2010.05.11 08:30