'뻘소리'에 해당되는 글 35건

  1. 2016.08.18 부스트 코루틴
  2. 2016.08.18 비구조적 프로그래밍
  3. 2016.08.18 아키텍처 프로그래밍
  4. 2016.08.18 제네릭 프로그래밍
  5. 2016.08.18 메타프로그래밍
뻘소리2016. 8. 18. 12:15

With Boost.Coroutine it is possible to use coroutines in C++. Coroutines are a feature of other programming languages, which often use the keyword yield for coroutines. In these programming languages, yield can be used like return. However, when yield is used, the function remembers the location, and if the function is called again, execution continues from that location.

C++ doesn’t define a keyword yield. However, with Boost.Coroutine it is possible to return from functions and continue later from the same location. The Boost.Asio library also uses Boost.Coroutine and benefits from coroutines.

There are two versions of Boost.Coroutine. This chapter introduces the second version, which is the current version. This version has been available since Boost 1.55.0 and replaces the first one.

Example 51.1. Using coroutines
#include <boost/coroutine/all.hpp>
#include <iostream>

using namespace boost::coroutines;

void cooperative(coroutine<void>::push_type &sink)
{
  std::cout << "Hello";
  sink();
  std::cout << "world";
}

int main()
{
  coroutine<void>::pull_type source{cooperative};
  std::cout << ", ";
  source();
  std::cout << "!\n";
}

Example 51.1 defines a function, cooperative(), which is called from main() as a coroutine.cooperative() returns to main() early and is called a second time. On the second call, it continues from where it left off.

To use cooperative() as a coroutine, the types pull_type and push_type are used. These types are provided by boost::coroutines::coroutine, which is a template that is instantiated with void in Example 51.1.

To use coroutines, you need pull_type and push_type. One of these types will be used to create an object that will be initialized with the function you want to use as a coroutine. The other type will be the first parameter of the coroutine function.

Example 51.1 creates an object named source of type pull_type in main()cooperative()is passed to the constructor. push_type is used as the sole parameter in the signature ofcooperative().

When source is created, the function cooperative(), which is passed to the constructor, is immediately called as a coroutine. This happens because source is based on pull_type. Ifsource was based on push_type, the constructor wouldn’t call cooperative() as a coroutine.

cooperative() writes Hello to standard output. Afterwards, the function accesses sink as if it were a function. This is possible because push_type overloads operator(). Whilesource in main() represents the coroutine cooperative()sink in cooperative()represents the function main(). Calling sink makes cooperative() return, and main()continues from where cooperative() was called and writes a comma to standard output.

Then, main() calls source as if it were a function. Again, this is possible because of the overloaded operator(). This time, cooperative() continues from the point where it left off and writes world to standard output. Because there is no other code in cooperative(), the coroutine ends. It returns to main(), which writes an exclamation mark to standard output.

The result is that Example 51.1 displays Hello, world!

You can think of coroutines as cooperative threads. To a certain extent, the functions main()and cooperative() run concurrently. Code is executed in turns in main() andcooperative(). Instructions inside each function are executed sequentially. Thanks to coroutines, a function doesn’t need to return before another function can be executed.

Example 51.2. Returning a value from a coroutine
#include <boost/coroutine/all.hpp>
#include <functional>
#include <iostream>

using boost::coroutines::coroutine;

void cooperative(coroutine<int>::push_type &sink, int i)
{
  int j = i;
  sink(++j);
  sink(++j);
  std::cout << "end\n";
}

int main()
{
  using std::placeholders::_1;
  coroutine<int>::pull_type source{std::bind(cooperative, _1, 0)};
  std::cout << source.get() << '\n';
  source();
  std::cout << source.get() << '\n';
  source();
}

Example 51.2 is similar to the previous example. This time the templateboost::coroutines::coroutine is instantiated with int. This makes it possible to return anint from the coroutine to the caller.

The direction the int value is passed depends on where pull_type and push_type are used. The example uses pull_type to instantiate an object in main()cooperative() has access to an object of type push_typepush_type sends a value, and pull_type receives a value; thus, the direction of the data transfer is set.

cooperative() calls sink, with a parameter of type int. This parameter is required because the coroutine was instantiated with the data type int. The value passed to sink is received from source in main() by using the member function get(), which is provided bypull_type.

Example 51.2 also illustrates how a function with multiple parameters can be used as a coroutine. cooperative() has an additional parameter of type int, which can’t be passed directly to the constructor of pull_type. The example uses std::bind() to link the function with pull_type.

The example writes 1 and 2 followed by end to standard output.

Example 51.3. Passing two values to a coroutine
#include <boost/coroutine/all.hpp>
#include <tuple>
#include <string>
#include <iostream>

using boost::coroutines::coroutine;

void cooperative(coroutine<std::tuple<int, std::string>>::pull_type &source)
{
  auto args = source.get();
  std::cout << std::get<0>(args) << " " << std::get<1>(args) << '\n';
  source();
  args = source.get();
  std::cout << std::get<0>(args) << " " << std::get<1>(args) << '\n';
}

int main()
{
  coroutine<std::tuple<int, std::string>>::push_type sink{cooperative};
  sink(std::make_tuple(0, "aaa"));
  sink(std::make_tuple(1, "bbb"));
  std::cout << "end\n";
}

Example 51.3 uses push_type in main() and pull_type in cooperative(), which means data is transferred from the caller to the coroutine.

This example illustrates how multiple values can be passed. Boost.Coroutine doesn’t support passing multiple values, so a tuple must be used. You need to pack multiple values into a tuple or another structure.

Example 51.3 displays 0 aaa1 bbb, and end.

Example 51.4. Coroutines and exceptions
#include <boost/coroutine/all.hpp>
#include <stdexcept>
#include <iostream>

using boost::coroutines::coroutine;

void cooperative(coroutine<void>::push_type &sink)
{
  sink();
  throw std::runtime_error("error");
}

int main()
{
  coroutine<void>::pull_type source{cooperative};
  try
  {
    source();
  }
  catch (const std::runtime_error &e)
  {
    std::cerr << e.what() << '\n';
  }
}

A coroutine returns immediately when an exception is thrown. The exception is transported to the caller of the coroutine where it can be caught. Thus, exceptions are no different than with regular function calls.

Example 51.4 shows how this works. This example will write the string error to standard output.


출처 - 부스트씨쁠쁠라이브러리

'뻘소리' 카테고리의 다른 글

컨텍스트 스위칭(Context Switching)  (0) 2016.10.04
람다 대수  (0) 2016.08.21
비구조적 프로그래밍  (0) 2016.08.18
아키텍처 프로그래밍  (0) 2016.08.18
제네릭 프로그래밍  (0) 2016.08.18
Posted by 멜데스
뻘소리2016. 8. 18. 12:13

비구조적 프로그래밍은 하나의 연속된 덩어리에 모든 코드를 넣는 프로그래밍 패러다임이다. 대비되는 개념으로는 구조적 프로그래밍이 있는데, 이는 프로그램의 작업이 (함수나 서브루틴으로 알려진) 더 작은 부분으로 나누어 필요할 때마다 호출하는 것이다. 비구조적 프로그래밍 언어는 코드의 특정부분으로 건너뛰는 GOTO문과 같은 흐름 제어문에 의존할 수밖에 없다.

구조화되지 않은 원시 코드는 읽고 디버그하기가 매우 어렵고, 구조적인 작성을 지원하는 프로그래밍 언어에서는 추천하지 않는다. 그러나 프로그램 구조는 항상 조건문과 GOTO문을 조합하여 구현할 수 있기 때문에 구조가 모든 언어에서 필요한 것은 아니다. MS-DOS배치 파일과 같은 많은 스크립트 언어나 베이직이나 포트란 같이 오래된 언어에서는 여전히 사용되기도 한다. GOTO문을 쓰는 것에 수행 속도상의 이점은 없다. (실제로, 컴파일러가 최적화 할 수 있는 것들을 혼란시켜 오히려 불이익이 될 수도 있다.)

어셈블리어는 대체로 비구조적 언어인데, 기본이 되는 기계어 코드가 구조적이지 않기 때문이다. 어셈블리 언어에 있는 유일한 구조는 함수의 시작과 끝 같이 컴파일 도구에서 쓰는 것들이다.


출처 - 위키

'뻘소리' 카테고리의 다른 글

람다 대수  (0) 2016.08.21
부스트 코루틴  (0) 2016.08.18
아키텍처 프로그래밍  (0) 2016.08.18
제네릭 프로그래밍  (0) 2016.08.18
메타프로그래밍  (0) 2016.08.18
Posted by 멜데스
뻘소리2016. 8. 18. 12:10

구조적 프로그래밍(structured programming)은 구조화 프로그래밍으로도 불리며 프로그래밍 패러다임의 일종인 절차적 프로그래밍의 하위 개념으로 볼 수 있다. GOTO문을 없애거나 GOTO문에 대한 의존성을 줄여주는 것으로 가장 유명하다.

역사적으로 구조적 프로그램을 작성하기 위하여 몇가지 다른 구조화 기법과 방법론이 개발되어왔다. 가장 일반적인 3가지는 다음과 같다.

  1. 잭슨의 구조적 프로그래밍 : 자료구조를 프로그램 구조에 맞추는 것에 중점을 두었다.
  2. 데이크스트라의 구조적 프로그래밍 : 프로그램의 논리 구조는 제한된 몇 가지 방법만을 이용하여 비슷한 서브 프로그램들로 구성된다. 프로그램에 있는 각각의 구조와 그 사이의 관계를 이해하면 프로그램 전체를 이해해야 하는 수고를 덜 수 있어, SoC에 유리하다.
  3. 데이크스트라의 관점에서 파생된 관점 : 하위 프로그램의 시작점은 한 군데이지만 끝점은 여러 개일 수 있다.

대부분의 사람들이 구조적 프로그래밍이라고 할 때 첫 번째 것을 제외한 둘 중에 하나를 말하는 것이며, 이것이 여기서 말하고자 하는 것이다.

요약[편집]

저수준 구조[편집]

저수준의 관점에서 구조적 프로그램은 간단하고, 계층적인 프로그램 제어 구조로 구성된다. 이 제어 구조들은 하나의 구문으로 간주되며, 동시에 더 간단한 구문들을 결합시키는 방법이다. 더 간단한 구문들은 또 다른 제어 구조일 수도 있고, 할당문이나 프로시저 호출과 같은 기본 구문일 수도 있다. 에츠허르 데이크스트라가 확인한 3가지 형태의 구조는 순차, 선택, 반복이다.

  • 순차(concatenation)는 구문 순서에 따라서 순서대로 수행된다는 것이다.
  • 선택(selection)은 프로그램의 상태에 따라서 여러 구문들 중에서 하나를 수행하는 것이다. 주로 if..then..else..endifswitchcase와 같은 키워드로 표현한다.
  • 반복(repetition)은 프로그램이 특정 상태에 도달할 때까지 구문을 반복하여 수행하거나, 집합체의 각각의 원소들에 대해 어떤 구문을 반복 수행하는 것이다. 보통 whilerepeatfordo..until 같은 키워드로 표현한다. 종종 반복 영역의 시작점을 하나로 하는 것이 추천되며, (원조 구조적 프로그래밍에서는 종료점도 하나로 해야한다고 추천하고,) 몇 가지 언어에서는 이것을 꼭 지켜야 하도록 하고 있다.

데이크스트라의 초창기 가드 명령어 언어같은 어떤 언어에서는 구조를 완전히 둘러싸는 if..fi와 같은 구문으로 구조의 단일성을 강조한다. C 같은 다른 언어들은 구조의 단일성을 강조하지 않는데, 잘못 이해하거나 잘못 수정할 수 있는 위험이 커지는 것은 아니다.

고수준 구조[편집]

코드 작성자는 큰 조각의 코드를 이해하기 쉬운 크기의 작은 하부 프로그램(함수, 프로시저, 메서드, 블록, 등)으로 나누어야 한다. 일반적으로 프로그램은 전역 변수는 거의 사용하지 않아야 하고 대신에 하부 프로그램은 지역 변수를 사용하거나, 값이나 참조에 의한 인자를 받아야 한다. 이런 기법은 전체 프로그램을 한번에 이해하지 않고, 분리된 작은 코드 조각을 쉽게 이해하는 데 도움을 준다.

설계[편집]

구조적 프로그래밍은 항상 그런 것은 아니지만 하향식 설계와 관련이 있다. 하향식 설계를 할 때, 설계자는 큰 규모의 프로그램을 더 작은 공정으로 나누어 구현하고, 각각 검사한 다음에 전체 프로그램으로 합친다.

구조적 프로그래밍 언어[편집]

모든 절차적 프로그래밍 언어에서 구조적 프로그래밍을 할 수 있다. 1970년쯤부터 구조적 프로그래밍이 인기있는 기법이 되었기 때문에, 대부분의 새로 나온 절차적 프로그래밍 언어들이 구조적 프로그래밍을 고취시키기 위한 특징을 추가하였고 구조화되지 않은 프로그래밍을 쉽게 하기 위한 특징들은 남겨둔 것들도 있었다. 잘 알려진 구조적 프로그래밍 언어에는 파스칼(Pascal)과 에이다(Ada)가 있다.

역사[편집]

이론적 기반[편집]

구조적 프로그램 정리는 구조적 프로그래밍의 이론적 기반이 되었다. 정리에 따르면, 프로그램을 결합하는 3가지 방법인 순차, 분기, 반복만으로 충분히 계산가능 함수를 표현할 수 있다. 이런 점은 구조적 프로그래밍 운동에서 나온 것은 아니지만, 이런 구조들은 중앙 처리 장치의 명령 주기뿐만 아니라 튜링 기계의 동작을 설명하는 데 충분하다. 따라서 이런 의미에서 프로세서는 항상 "구조적 프로그램"을 실행한다. 구조적 프로그램이 아닌 기억 장치의 다른 부분에서 읽는 명령을 수행해도 그러하다. 1966년 뵘(Böhm)과 야코피니(Jacopini)의 글을 데이크스트라가 인용하였기 때문에 구조적 프로그래밍의 최초의 이론적 기반이라고 하기도 한다. 구조적 프로그램 정리에 구조적 프로그램을 어떻게 작성하고 분석하는지에 대해서는 나와있지 않다. 이 내용들은 1960년대 후반과 1970년대 초반에 개발되었는데 주로 데이크스트라플로이드그리즈가 많은 공헌을 했다.

논쟁[편집]

구조적 프로그래밍의 선구적 실천가(얼리어답터)인 플로저는 구조적 프로그램 정리에 대한 그의 반응을 이렇게 설명했다.:

우리는 이 흥미로운 소식을 어셈블리 프로그래머들에게 알려주면서 마음을 돌려보려 하였지만, 이 덜된 어셈블리 프로그래머들은 비비꼬인 로직의 비트들을 만들어내면서 계속해서 '이런건 구조화가 안될껄?'이라고 말하고 있다. 뵘과 야코피니의 증명을 보여주어도, 우리가 구조적 코드를 성공적으로 계속해서 만들어서 보여주어도, 그들은 구조화된 프로그래밍 적응 준비를 하루도 앞당기지 않았다.

1967년CACM에 데이크스트라의 "GOTO문의 해로움"(Go to statement considered harmful)라는 서한이 실렸다. 이 글에서 그는 뵘과 야코피니의 증명을 인용하면서, 고급언어에서 GOTO 명령을 제거하는 것이 코드의 질을 높일 수 있다고 했다. 이 글은 주로 구조적 프로그래밍 논쟁의 시작점으로 인용된다.

비록 플로저가 언급했듯이 다수의 프로그래머들이 이 정리에 익숙하지 않다고 해도, 이런 프로그래머들을 양성할 가치가 충분히 있을 정도로 몇 년간 소프트웨어 개발은 간결성, 품질, 개발 시간의 측면에서 향상되었다. 데이크스트라는 구조의 종류를 제한하는 것이 프로그래머가 생각하는 데 집중하는 것을 돕고, 관리 가능한 절차로 분석하여 프로그램의 유효성을 더 간단히 보장할 수 있다고 했다. 그는 1969년구조적 프로그래밍에 대한 글에서 이렇게 썼다.:

우리는 정확한 프로그램을 작성하는 프로그래머의 직분을 수행해야 할 뿐만 아니라, 그것의 정확성을 납득가능한 방법으로 증명하는 역할도 수행해야 한다. 위에서 한 언급은 프로그래머가 작성하는 모든 것은 유효하게 구조화되어야 한다는 것에 뜻 깊은 영향을 끼친다. (중략) 프로그램의 정확성뿐만 아니라 프로그램의 적응성과 관리성까지 내가 신경 쓰고 있다는 것이 더욱 명백해진다.1

도널드 커누스(Donald Knuth)는 프로그램이 입증가능성을 염두에 두고 작성되어야 한다는 원리는 받아들였으나 GOTO문을 없애는 것은 받아들이지 않았고 지금도 받아들이지 않는다. 1974년, 그의 논문, "GOTO문이 포함된 구조적 프로그래밍"에서 직접적인 분기를 하여 입증가능성을 희생시키지 않으면서도 더 간결하고 효율적인 코드를 작성할 수 있는 몇 가지 예제를 보였다. 카누스는 좀 더 완화된 구조 제한을 제안했다. 그것은 프로그램의 순서도를 그린다면 왼쪽에는 아래쪽으로 가는 가지(branches)만, 오른쪽에는 위쪽으로 가는 가지만 그려야하며 그 가지들이 서로 교차하지 않아야 한다는 것이다. 컴파일러와 그래프 이론에 정통해 있는 많은 사람들이 축소 가능한 흐름도(reducible flow graphs)만을 허용해야한다고 이 생각을 옹호했다.

구조적 프로그램 이론가들은 1970년대 IBM의 연구원 밀즈가 구조적 프로그래밍 이론에 대한 그의 해석을 뉴욕타임즈의 인덱싱 시스템 개발자들에게 적용한 일이 있은 후에 대부분이 합의를 봤다. 이 계획은 공학적으로 크게 성공하였다. 데이크스트라가 밀즈의 해석이 출판된 것들과 다르다며 비판하였지만, 다른 회사의 관리자들까지도 구조적 프로그래밍의 채택을 지원하기 위하여 밀즈의 해석을 인용했다.

1987년이 되어서도 여전히 컴퓨터 과학 간행물에서 구조적 프로그래밍에 대해 의문점이 제기되었다. 프랭크 루빈은 그 해에 "GOTO문의 해로움의 해로움"('Go to statement considered harmful' considered harmful)이라는 글을 썼다. 루빈은 물론이거니와 양보하라고 한 다른 필자들까지도 날카롭게 비판한 데이크스트라의 응답과 함께 수많은 반대 의견이 뒤따랐다.

결과[편집]

20세기의 막바지에 이르자, 대부분의 컴퓨터 과학자들은 구조적 프로그래밍의 개념을 배우고 적용하는 것은 유용하다고 확신했다. 포트란코볼베이직과 같이 프로그래밍 구조가 원래 취약한 고급 프로그래밍 언어들은 이제 그런 구조를 가지고 있다. GOTO문 제멋대로 사용하는 것을 받아들이는 프로그래밍 교육자들은 찾기가 힘들어졌다.

프로그래머가 경험을 쌓을수록 엄격한 의미의 구조적 프로그래밍을 침해하는 어떤 부분이 있는지를 이해하기가 쉽다는 것을 알았고, 널리 퍼진 몇몇 프로그래밍 언어들은 직접적인 분기문을 제한하고 있으며 예외처리를 이런 상황에서 사용할 수 있게 하고 있다. 주요한 산업용 언어들은 자바와 같은 언어들을 제외하고는 프로시저 내에서의 직접 분기를 위하여 GOTO문을 여전히 유지하고 있다. 데이크스트라가 구조적 프로그래밍을 표준 교육과정에 편입시키는 데는 성공했지만 엄격한 조건을 고수하는 데는 성공하지 못하였다.

엄격한 조건을 만족시키지 못하는 상황[편집]

예외 처리[편집]

대부분의 경우에 하위프로그램에 여러 개의 시작점이 있는 것은 아니지만, 여러 개의 종료점을 가지는 경우는 있다. 주로 하위프로그램이 더이상 할 일이 없거나 더이상 계속하지 못하는 상황이 된 경우이다.

다음은 파일에서 자료를 읽어서 처리하는 간단한 프로시저의 전형적인 예이다:

open file;
while (reading not finished) {
  read some data;
  if (error) {
    stop the subprogram and inform rest of the program about the error;
  }
}
process read data;
finish the subprogram;

5번째 줄에서 멈추고 알리는 것은 예외를 발생시키거나, 제 2의 리턴을 하거나, 레이블한 루프로 빠져나가거나, 심지어는 goto를 써도 할 수 있다. 프로시저가 2개의 종료점을 갖기 때문에 데이크스트라의 구조적 프로그래밍의 규칙에 어긋난다. 종료점을 하나로 하는 규칙을 지키려고 하면 복잡해진다. 에러 상황이 더 있다면, 청소 규칙이 서로 달라서, 오히려 goto문을 사용한 비구조적인 것보다 훨씬 읽거나 이해하기 어렵게 될 것이다. 반면에 그런 규칙을 따르지 않는 구조적 프로그래밍은 코드를 아주 깔끔하고 읽기 쉽게 할 것이다.

대부분의 언어는 구조적 프로그래밍에서의 여러 종료점을 지원한다. C는 continue, break, return과 같이 여러가지 경로로 구조에서 빠져나가는 것을 허용하고, 더 새로운 언어들은 레이블한 루프(전자와 비슷하지만 제일 안쪽 루프 뿐만 아니라 그 이상도 빠져나갈 수 있게 해 준다)와 예외처리를 지원한다.

상태 기계[편집]

특히 구문분석기와 통신 규약 같은 프로그램들은 상태들이 있어서 기본 구조들로 줄이기가 쉽지 않다. 각각의 상태 변화를 분리하여 하위프로그램을 만들고 변수를 이용하여 활동중인 상태를 나타내면 가능하긴 하다. 하지만, 카누스를 포함한 일부 프로그래머들은 상태의 변화를 새로운 상태로 직접 분기하는 것을 더 좋아한다.

현대적 가치[편집]

구조적 프로그래밍에 대한 논의는 많은 새로운 언어를 낳았으며, 기존의 언어에 구조적인 면이 추가되는 등 언어의 발전에 도움이 되었다. 그리고 이후에 나온 프로그래밍 패러다임들에도 영향을 끼쳤다.

구조적 프로그래밍은 프로그래머의 습관을 바꾸었다. 프로그램의 정확성을 증명하는 문제를 떠나서 데이크스트라가 그의 논문에서 말한 대로 시간에 따라 변하는 동적인 과정을 시각화하는 것은 인간에게 매우 어려운 일이다. 꼭 GOTO문만의 문제가 아니라 구조화된 흐름 제어문을 사용한다고 할지라도 너무 복잡하게 중첩되어 있거나 스코프의 길이가 너무 긴 코드를 작성한다거나 너무 긴 길이의 하위프로그램을 작성하는 일을 가급적 피하게 경향이 생겼다. 그리고 이런 습관은 다른 사람이 작성한 프로그래밍 코드를 쉽게 이해하는 데 도움을 준다.

데이크스트라가 쓴 "GOTO문의 해로움"이라는 논문은 이후 "...의 해로움"이라는 유행을 낳기도 하였다. 이는 컴퓨터 과학에서 과도하게 사용되는 어떤 것에 대한 것을 비판하는 데 많이 사용되었다.

읽을거리[편집]

참고문헌[편집]

  1. (영어) 에츠허르 데이크스트라Notes on Structured Programming, pg. 6
  2. (영어) 뵘, C. 와 야코피니, G.: Flow diagrams, Turing machines and languages with only two formation rules, CACM 9(5), 1966.

바깥 고리[편집]


출처 - 위키

'뻘소리' 카테고리의 다른 글

람다 대수  (0) 2016.08.21
부스트 코루틴  (0) 2016.08.18
비구조적 프로그래밍  (0) 2016.08.18
제네릭 프로그래밍  (0) 2016.08.18
메타프로그래밍  (0) 2016.08.18
Posted by 멜데스
뻘소리2016. 8. 18. 12:07

제네릭 프로그래밍(영어: Generic programming)은 데이터 형식에 의존하지 않고, 하나의 값이 여러 다른 데이터 타입들을 가질 수 있는 기술에 중점을 두어 재사용성을 높일 수 있는 프로그래밍 방식이다.

제네릭 프로그래밍은 여러가지 유용한 소프트웨어 컴포넌트들을 체계적으로 융합하는 방법을 연구하는 것으로 그 목적은 알고리즘, 데이터 구조, 메모리 할당 메커니즘, 그리고 기타 여러 소프트웨어적인 장치들을 발전시켜 이들의 재사용성, 모듈화, 사용 편이성을 보다 높은 수준으로 끌어올리고자 하는 것이다.


출처 - 위키

'뻘소리' 카테고리의 다른 글

람다 대수  (0) 2016.08.21
부스트 코루틴  (0) 2016.08.18
비구조적 프로그래밍  (0) 2016.08.18
아키텍처 프로그래밍  (0) 2016.08.18
메타프로그래밍  (0) 2016.08.18
Posted by 멜데스
뻘소리2016. 8. 18. 12:06

메타프로그래밍이란 자기 자신 혹은 다른 컴퓨터 프로그램을 데이터로 처리함으로써 프로그램을 작성·수정하는 프로그램을 작성하는 것을 말한다. 넓은 의미에서, 런 타임에 수행해야 할 작업의 일부를 컴파일 타임 동안 수행하는 프로그램을 말하기도 한다.

메타 프로그래밍에 이용되는 언어를 메타 언어라고 하고, 메타 프로그래밍의 대상이 되는 언어를 대상 언어라고 한다. 한 프로그래밍 언어가 자기 자신의 메타 언어가 되는 것을 반영이라고 한다.

메타 프로그래밍이 동작하는 방식은 세 가지 종류가 있다[출처 필요]. 첫째 방식은, 런타임 엔진의 코드를 API를 통해 프로그램에 노출시키는 방식이다. 둘째 방식은, 문자열이나 혹은 다른 형태로 된 프로그래밍 명령을동적으로 수행시키는 방식이다. 둘째 방식을 이용하면 프로그램이 프로그램을 작성하게 할 수 있다[1]. 한 언어가 이 두 방식을 동시에 취할 수도 있으나, 대개의 언어들은 둘 중 한 방식으로 치우치는 경향이 있다.

셋째 방식은, 해당 언어의 범주를 완전히 벗어나는 것이다. 범용 프로그램 변환(program transformation) 시스템은 일반적인 메타프로그래밍을 직접 구현한다. 이와 같은 방식은 해당 언어에서 메타 프로그램 지원 여부와 상관없이 거의 모든 대상 언어에 적용될 수 있다.


출처 - 위키

'뻘소리' 카테고리의 다른 글

람다 대수  (0) 2016.08.21
부스트 코루틴  (0) 2016.08.18
비구조적 프로그래밍  (0) 2016.08.18
아키텍처 프로그래밍  (0) 2016.08.18
제네릭 프로그래밍  (0) 2016.08.18
Posted by 멜데스