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


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.