기능적 언어의 비동기 프로그래밍


31

저는 주로 C / C ++ 프로그래머입니다. 이는 대부분의 경험이 절차 및 객체 지향 패러다임에 관한 것임을 의미합니다. 그러나 많은 C ++ 프로그래머가 알고 있듯이 C ++은 수년에 걸쳐 기능적 스타일로 강조되어 마침내 C ++ 0x에서 람다와 클로저를 추가하는 중입니다.

그럼에도 불구하고 C ++을 사용하여 기능적 스타일로 코딩하는 데 상당한 경험이 있지만 Lisp, Haskell 등과 같은 실제 기능 언어에 대한 경험은 거의 없습니다.

순전히 기능적인 언어에서 "부작용 없음"이라는 아이디어가 특히 동시성 및 분산 컴퓨팅에 대한 응용 프로그램과 관련하여 항상 흥미를 끌기 때문에 최근에 이러한 언어를 연구하기 시작했습니다.

그러나 C ++ 배경에서 비롯된이 "부작용 없음"철학이 비동기식 프로그래밍에서 어떻게 작동하는지에 대해서는 혼란스러워합니다. 비동기 프로그래밍이란 비동기식으로 발생하는 이벤트를 처리하기 위해 사용자가 제공 한 이벤트 핸들러를 전달하는 모든 프레임 워크 / API / 코딩 스타일을 의미합니다 (프로그램 흐름 외부). 여기에는 Boost.ASIO와 같은 비동기 라이브러리 또는 일반 C 신호 처리기 또는 Java GUI 이벤트 처리기

이들 모두 공통점은 비동기 프로그래밍의 특성상 프로그램 의 주요 흐름이 비동기 이벤트 핸들러가 호출되었음을 인식하기 위해 부작용 (상태)을 작성 해야하는 것 같습니다 . 일반적으로 Boost.ASIO와 같은 프레임 워크에서 이벤트 핸들러 는 객체의 상태를 변경 하여 이벤트 의 효과가 이벤트 핸들러 함수의 수명을 넘어 전파되도록합니다. 실제로 이벤트 핸들러는 무엇을 할 수 있습니까? 호출 지점이 없기 때문에 호출 지점으로 값을 "반환"할 수 없습니다. 이벤트 핸들러는 프로그램의 주요 흐름의 일부가 아니므로 실제 프로그램에 영향을 줄 수있는 유일한 방법은 일부 상태 (또는 longjmp다른 실행 지점) 를 변경하는 것 입니다.

따라서 비동기 프로그래밍은 부작용을 비동기 적으로 생성하는 것입니다. 이것은 함수형 프로그래밍의 목표와 완전히 상충되는 것 같습니다. 이 두 패러다임은 어떻게 실용 언어로 화해합니까?


3
와우, 나는 단지 이것을 좋아하는 질문을 작성하려고했고 그것을 넣는 방법을 몰랐고 제안에서 이것을 보았습니다!
Amogh Talpallikar

답변:


11

함수형 프로그래밍에 대한 이해가 너무 극단적이라고 생각하는 것을 제외하고는 모든 논리가 건전합니다. 실제 기능 프로그래밍에서 객체 지향 또는 명령 프로그래밍과 마찬가지로 사고 방식 과 문제에 대한 접근 방식에 관한 것입니다. 응용 프로그램 상태를 수정하면서 기능 프로그래밍의 정신으로 프로그램을 작성할 수 있습니다.

실제로 실제로 작업을 수행 하려면 응용 프로그램 상태를 수정 해야 합니다. 하스켈 녀석은 그들의 상태 변화를 모나드에 싸서 프로그램이 '순수하다'고 말할 것입니다. 그러나 그들의 프로그램은 여전히 ​​외부 세계와 상호 작용합니다. (그렇지 않으면 요점이 뭐야!)

기능적 프로그래밍은 의미가있을 때 "부작용 없음"을 강조합니다. 그러나 당신이 말한 것처럼 실제 프로그래밍을하려면 세상의 상태를 수정해야합니다. (예를 들어, 이벤트 응답, 디스크 쓰기 등)

함수형 언어의 비동기 프로그래밍에 대한 자세한 내용은 F #의 비동기 워크 플로 프로그래밍 모델을 참조하십시오. 라이브러리 내에서 스레드 전이에 대한 모든 복잡한 세부 사항을 숨기면서 기능성 프로그램을 작성할 수 있습니다. (하스켈 스타일의 모나드와 매우 유사한 방식으로)

스레드의 '본문'이 단순히 값을 계산하는 경우 여러 스레드를 생성하고 병렬로 값을 계산하도록하는 것은 여전히 ​​기능적 패러다임 내에 있습니다.


5
또한 Erlang을 보면 도움이됩니다. 언어는 (모든 데이터가 불변) 매우 단순한 순수하고, 모든 비동기 처리에 대해.
9000

기본적으로 기능적 접근 방식의 이점을 이해하고 중요한 경우에만 상태를 변경하면 Java와 같은 작업을 수행하더라도 상태를 수정하는시기와 그러한 항목을 제어하는 ​​방법을 자동으로 알 수 있습니다.
Amogh Talpallikar

동의하지 않음-프로그램이 '순수한'기능으로 구성되었다는 것이 외부 세계와 반복되지 않는다는 것을 의미하지는 않으며, 한 세트의 인수에 대한 프로그램의 모든 기능이 항상 동일한 결과를 반환한다는 의미입니다. 실용적 관점에서 볼 때 이러한 프로그램은 버그가 적고 '테스트 가능'하며 함수의 성공적인 실행이 수학적으로 증명 될 수 있기 때문에 (순도) 큰 문제입니다.
길 베이츠

8

이것은 흥미로운 질문입니다. 가장 흥미로운 점은 Clojure에서 채택 되고이 비디오에서 설명 된 접근 방식입니다.

http://www.infoq.com/presentations/Value-Identity-State-Rich-Hickey

기본적으로 제안 된 "솔루션"은 다음과 같습니다.

  • 대부분의 코드를 변경 불가능한 데이터 구조와 부작용없이 클래식 한 "순수한"함수로 작성
  • 소프트웨어 트랜잭션 메모리 규칙에 따라 변경을 제어하는 ​​관리되는 참조를 사용하여 부작용이 격리됩니다 (예 : 변경 가능한 상태에 대한 모든 업데이트는 적절한 격리 된 트랜잭션 내에서 발생 함)
  • 이 세계관을 취하면 비동기 "이벤트"가 업데이트 자체가 순수한 함수 인 변경 가능한 상태의 트랜잭션 업데이트에 대한 트리거로 볼 수 있습니다.

나는 아마도 다른 사람들처럼 아이디어를 명확하게 표현하지는 않았지만 이것이 일반적인 아이디어를 제공하기를 바랍니다. 기본적으로 동시 STM 시스템을 사용하여 순수한 기능 프로그래밍과 비동기 이벤트 처리 사이의 "브리지"를 제공합니다.


6

한 가지 참고 사항 : 기능적 언어는 순수하지만 런타임은 아닙니다.

예를 들어, Haskell 런타임에는 큐, 스레드 멀티플렉싱, 가비지 콜렉션 등이 포함됩니다.

좋은 예는 게으름입니다. Haskell은 게으른 평가 (실제로 기본값)를 지원합니다. 작업을 준비하여 지연 값을 생성 한 다음이 값의 사본을 여러 개 생성 할 수 있으며 필요하지 않은 한 여전히 "게으름"입니다. 결과가 필요하거나 런타임이 시간을 찾은 경우 실제로 값이 계산되고 게으른 객체의 상태가 더 이상 결과를 얻기 위해 더 이상 계산을 수행 할 필요가 없음을 반영하여 변경됩니다. 이제는 모든 참조를 통해 사용할 수 있으므로 순수한 언어 임에도 불구하고 객체의 상태가 변경되었습니다.


2

이 "부작용 없음"철학이 비동기 프로그래밍에서 어떻게 작동하는지에 대해서는 혼란스러워합니다. 비동기 프로그래밍으로 나는 ...

그렇다면 요점이 될 것입니다.

부작용이없는 사운드는 상태에 의존하는 프레임 워크와 호환되지 않습니다. 새로운 프레임 워크를 찾으십시오.

예를 들어 Python의 WSGI 표준을 사용하면 부작용이없는 응용 프로그램을 만들 수 없습니다.

아이디어는 다양한 "상태 변경"이 점진적으로 구축 될 수있는 값의 환경에 반영된다는 것입니다. 각 요청은 변환의 파이프 라인입니다.


"부족한 응용 프로그램을 만들 수 없습니다"어딘가에 단어가 빠져 있다고 생각합니다.
Christopher Mahan

1

C를 배우고 난 후 Borland C ++에서 캡슐화를 배웠는데, Borland C ++에 제네릭을 가능하게하는 템플릿이 없었을 때 객체 지향 패러다임이 불편했습니다. 좀 더 자연스러운 계산 방법은 파이프를 통해 데이터를 필터링하는 것 같습니다. 외부 스트림은 부작용으로 생각하기보다는 내부 불변 입력 스트림과 분리 된 독립적 인 동일성을 가졌다. 즉, 모든 데이터 소스 (또는 필터)는 다른 것으로부터 자율적이었다. 키 누르기 (예제 이벤트)는 비동기 사용자 입력 조합을 사용 가능한 키 코드로 제한했습니다. 함수는 입력 매개 변수 인수에서 작동하며 클래스에 의해 캡슐화 된 상태는 임의의 함수에서 해당 인수를 남용하는 것을 막기 위해 경계 컨텍스트에주의를 기울이는 것 외에도 작은 함수 하위 집합 사이에 반복 인수를 명시 적으로 전달하는 것을 피하는 바로 가기입니다.

예를 들어 특정 패러다임을 엄격하게 준수하면 누출 된 추상화를 처리하기가 불편합니다. JRE, DirectX, .net 대상 객체 지향 제안자와 같은 상용 런타임. 불편을 막기 위해 언어는 Haskell처럼 학술적으로 정교한 모나드를 선택하거나 F #과 같은 유연한 다중 패러다임 지원을 선택합니다. 캡슐화가 다중 상속 유스 케이스에서 유용하지 않으면 다중 패러다임 접근 방식이 때로는 복잡한 패러다임 특정 프로그래밍 패턴에 대한 탁월한 대안이 될 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.