반응 형 프로그래밍 에 관한 Wikipedia 기사를 읽었습니다 . 또한 기능적 반응성 프로그래밍 에 관한 작은 기사를 읽었습니다 . 설명은 매우 추상적입니다.
- FRP (기능적 반응성 프로그래밍)는 실제로 무엇을 의미합니까?
- 반응 형 프로그래밍 (비 반응 형 프로그래밍과 달리)은 무엇으로 구성됩니까?
저의 배경은 명령형 / OO 언어로되어 있으므로이 패러다임과 관련된 설명을 부탁드립니다.
반응 형 프로그래밍 에 관한 Wikipedia 기사를 읽었습니다 . 또한 기능적 반응성 프로그래밍 에 관한 작은 기사를 읽었습니다 . 설명은 매우 추상적입니다.
저의 배경은 명령형 / OO 언어로되어 있으므로이 패러다임과 관련된 설명을 부탁드립니다.
답변:
FRP에 대한 느낌을 원한다면 1998 년 의 오래된 Fran 튜토리얼 ( 애니메이션 일러스트레이션)을 시작할 수 있습니다. 논문의 경우 Functional Reactive Animation 으로 시작한 다음 내 홈페이지의 발행물 링크 및 Haskell Wiki 의 FRP 링크에 대한 링크를 확인하십시오 .
개인적으로, FRP가 어떻게 구현 될 수 있는지를 다루기 전에 FRP의 의미 에 대해 생각하고 싶습니다 . (사양이없는 코드는 질문이없는 답변이므로 "잘못된 것"도 아닙니다.) 따라서 Thomas K가 다른 답변 (그래프, 노드, 가장자리, 발사, 실행, 기타). 가능한 구현 스타일은 많지만 FRP 가 무엇인지 구현하는 것은 없습니다 .
나는 FRP가 " '시간이 지남에 따라 값을 나타내는 데이터 유형"에 관한 Laurence G의 간단한 설명과 공감합니다. 기존의 명령형 프로그래밍은 상태 및 돌연변이를 통해 이러한 동적 값을 간접적으로 만 캡처합니다. 완전한 역사 (과거, 현재, 미래)에는 일등석 표현이 없습니다. 또한 명령형 패러다임이 일시적으로 분리되기 때문에 이산 적으로 진화하는 값만 (간접적으로) 캡처 할 수 있습니다. 반대로, FRP는 이러한 진화하는 값을 직접 캡처 하며 지속적으로 진화하는 값 에는 어려움이 없습니다 .
FRP는 또한 명령형 동시성 (imperative concurrency)을 괴롭히는 이론적 및 실용적 쥐의 둥지를 무시하지 않고 동시에 진행된다는 점에서 특이합니다. 의미 상 FRP의 동시성은 세밀 하고 결정적 이며 연속적 입니다. (구현이 아닌 의미에 대해 이야기하고 있습니다. 구현에는 동시성 또는 병렬 처리가 포함될 수도 있고 포함되지 않을 수도 있습니다.) 의미 적 결정은 엄격하고 비공식적 인 추론에 매우 중요합니다. 동시성은 비 결정적 인터리빙으로 인해 명령형 프로그래밍에 엄청난 복잡성을 추가하지만 FRP에서는 쉽지 않습니다.
FRP 란 무엇입니까? 직접 발명했을 수도 있습니다. 다음 아이디어로 시작하십시오.
동적 / 진화하는 값 (즉, "시간이 지남에 따른 값")은 그 자체로 일류 값입니다. 그것들을 정의하고 결합하여 기능으로 전달하거나 전달할 수 있습니다. 나는 이것을 "행동"이라고 불렀다.
동작은 일정한 (정적) 동작 및 시간 (시계와 같은)과 같은 몇 가지 기본 요소로 구성된 다음 순차적 및 병렬 조합으로 구성됩니다. n 동작은 "정적"인 n-ary 함수 (정적 값)를 적용하여 시간이 지남에 따라 지속적으로 결합됩니다.
불연속 현상을 설명하기 위해, 다른 유형 (가족)의 "이벤트"가 있으며, 각 유형에는 스트림 (유한 또는 무한)이 있습니다. 각 발생에는 관련 시간과 값이 있습니다.
모든 행동과 사건을 구성 할 수있는 구성 어휘를 생각해 내려면 몇 가지 예를 들어보십시오. 보다 일반적인 / 간단한 조각으로 해체하십시오.
당신이 탄탄한 기초에 있다는 것을 알기 위해, denatotional semantics의 기술을 사용하여 전체 모델에 구성 기초를 제공하십시오. 이는 단지 (a) 각 유형에 해당하는 단순하고 정확한 수학적 유형의 "의미"가 있고, b) 각 기본 요소와 연산자는 구성 요소의 의미에 따라 단순하고 정확한 의미를 갖습니다. 절대로 구현 고려 사항을 탐색 프로세스에 혼합 하지 마십시오 . 이 설명이 이해하기 어려운 경우 (a) 유형 클래스 형태의 Denotational 디자인 , (b) Push-Pull 기능 반응 프로그래밍 (구현 비트 무시) 및 (c) Dentational Semantics Haskell Wikibooks 페이지를 참조하십시오.. 변형 적 의미론은 두 명의 설립자 Christopher Strachey와 Dana Scott의 두 부분으로 구성되어 있습니다. 더 쉽고 유용한 Strachey 부분과 더 어렵고 덜 유용한 (소프트웨어 디자인) Scott 부분입니다.
이러한 원칙을 고수하면 FRP의 정신으로 뭔가를 얻을 것으로 기대합니다.
이 원칙들을 어디서 얻었습니까? 소프트웨어 디자인에서 나는 항상 같은 질문을한다 : "무엇을 의미 하는가?" Denotational semantics는이 질문에 대한 정확한 프레임 워크를 제공했으며, 운영 또는 공리적 시맨틱과 달리 내 미학에 맞는 하나의 프레임 워크를 제공했습니다. 그래서 나는 행동이 무엇인지 스스로에게 물었다. 나는 명령형 계산의 시간적으로 별개의 특성 이 행동 자체에 대한 자연스러운 설명이 아니라 특정 스타일의 기계에 대한 수용이라는 것을 곧 깨달았습니다 . 제가 생각할 수있는 가장 간단한 행동 설명은 단순히 "연속적인 시간의 함수"입니다. 이것이 바로 저의 모델입니다. 유감스럽게도,이 모델은 쉽고 결정적인 연속성, 결정 성 동시성을 처리합니다.
이 모델을 정확하고 효율적으로 구현하는 것은 상당히 어려운 일이지만 다른 이야기입니다.
순수 기능 프로그래밍에서는 부작용이 없습니다. 많은 유형의 소프트웨어 (예 : 사용자 상호 작용이있는 모든 것)의 부작용에는 일정 수준이 필요합니다.
기능적 스타일을 유지하면서 동작과 같은 부작용을 얻는 한 가지 방법은 기능적 반응성 프로그래밍을 사용하는 것입니다. 이것은 기능 프로그래밍과 반응 형 프로그래밍의 조합입니다. (귀하가 연결 한 Wikipedia 기사는 후자에 관한 것입니다.)
반응 형 프로그래밍의 기본 개념은 "시간이 지남에 따라"값을 나타내는 특정 데이터 유형이 있다는 것입니다. 이러한 변경 시간 값을 포함하는 계산 자체는 시간이 지남에 따라 변경되는 값을 갖습니다.
예를 들어, 마우스 좌표를 시간에 따른 정수 값으로 나타낼 수 있습니다. 우리가 (의사 코드)와 같은 것을 가지고 있다고 가정 해 봅시다.
x = <mouse-x>;
y = <mouse-y>;
언제든지 x와 y는 마우스 좌표를 갖습니다. 비 반응 형 프로그래밍과 달리이 할당은 한 번만 수행하면되며 x 및 y 변수는 자동으로 "최신"상태를 유지합니다. 반응 형 프로그래밍과 기능적 프로그래밍이 함께 잘 작동하는 이유는 다음과 같습니다.
그런 다음이를 기반으로 계산을 수행하면 결과 값도 시간이 지남에 따라 변경되는 값이됩니다. 예를 들면 다음과 같습니다.
minX = x - 16;
minY = y - 16;
maxX = x + 16;
maxY = y + 16;
이 예제에서는 minX
항상 마우스 포인터의 x 좌표보다 16이 작습니다. 반응 인식 라이브러리를 사용하면 다음과 같이 말할 수 있습니다.
rectangle(minX, minY, maxX, maxY)
마우스 포인터 주위에 32x32 상자가 그려지고 움직일 때마다 추적합니다.
다음은 기능적 반응성 프로그래밍에 대한 아주 좋은 논문입니다 .
sqrt(x)
매크로로 C를 호출하면 계산 sqrt(mouse_x())
하고 두 배로 돌려줍니다. 진정한 기능적 반응 형 시스템에서는 sqrt(x)
새로운 "시간에 따른 두 배"를 반환합니다. FR 시스템을 시뮬레이션하려고한다면 #define
매크로를 선호하는 변수를 맹세해야합니다. FR 시스템은 일반적으로 재 계산이 필요할 때만 물건을 다시 계산하지만 매크로를 사용하면 하위 표현에 이르기까지 모든 것을 지속적으로 재평가해야합니다.
프로그램이 스프레드 시트이고 모든 변수가 셀이라는 것을 상상하는 것이 첫 번째 직관에 도달하는 쉬운 방법입니다. 스프레드 시트의 셀 중 하나라도 변경되면 해당 셀을 참조하는 모든 셀도 변경됩니다. FRP와 동일합니다. 이제 일부 셀이 자체적으로 변경되거나 외부 환경에서 가져 온다고 상상해보십시오. GUI 상황에서 마우스의 위치가 좋은 예가됩니다.
그것은 반드시 많은 것을 놓친다. 실제로 FRP 시스템을 사용하면 은유가 매우 빠르게 분해됩니다. 우선, 개별 이벤트 (예 : 마우스 클릭)도 모델링하려는 시도가 있습니다. 나는 이것이 당신에게 그것이 어떤 것인지 생각하기 위해 여기에 두는 것입니다.
나에게 그것은 상징의 두 가지 다른 의미입니다 =
.
x = sin(t)
수단, 즉 x
이다 다른 이름 에 대한 sin(t)
. 따라서 글쓰기 x + y
는와 같습니다 sin(t) + y
. 함수형 리 액티브 프로그래밍은 이런 점에서 수학과 같습니다. 작성하면 사용 당시 x + y
의 값이 무엇이든 계산 t
됩니다.x = sin(t)
할당은 할당시 할당 x
된 값 을 저장 한다는 의미입니다 sin(t)
.x = sin(t)
평균 x
은 sin(t)
주어진 값입니다 t
. 기능적 으로 다른 이름 이 아닙니다sin(t)
. 그렇지 않으면입니다 x(t) = sin(t)
.
2 + 3 = 5
또는 a**2 + b**2 = c**2
.
좋아, 배경 지식과 당신이 지적한 Wikipedia 페이지를 읽음으로써, 반응성 프로그래밍은 데이터 흐름 컴퓨팅과 유사하지만 특정 외부 "자극"이 발생하여 노드 세트를 실행하여 계산을 수행하는 것으로 보입니다.
예를 들어 음악 재생 응용 프로그램의 볼륨 컨트롤과 같은 사용자 인터페이스 컨트롤을 터치하면 다양한 표시 항목과 실제 오디오 출력 볼륨을 업데이트해야하는 UI 디자인에 매우 적합합니다. 직접 그래프에서 노드와 관련된 값을 수정하는 것과 일치하는 볼륨 (슬라이더라고 가정)을 수정하면
해당 "볼륨 값"노드의 가장자리를 가진 다양한 노드가 자동으로 트리거되며 필요한 계산 및 업데이트가 자연스럽게 응용 프로그램을 통해 리플됩니다. 응용 프로그램은 사용자 자극에 "반응"합니다. 기능적 반응 형 프로그래밍은 기능적 언어 또는 일반적으로 기능적 프로그래밍 패러다임 내에서이 아이디어를 구현 한 것일뿐입니다.
"데이터 흐름 컴퓨팅"에 대한 자세한 내용은 Wikipedia에서 또는 즐겨 찾는 검색 엔진을 사용하여이 두 단어를 검색하십시오. 일반적인 아이디어는 다음과 같습니다. 프로그램은 노드에 대한 유 방향 그래프이며 각각 간단한 계산을 수행합니다. 이러한 노드는 일부 노드의 출력을 다른 노드의 입력에 제공하는 그래프 링크를 통해 서로 연결됩니다.
노드가 실행되거나 계산을 수행하면 해당 출력에 연결된 노드에 해당 입력이 "트리거"또는 "표시"됩니다. 모든 입력이 트리거 / 표시 / 사용 가능한 모든 노드가 자동으로 실행됩니다. 반응 형 프로그래밍이 정확히 어떻게 구현되는지에 따라 그래프가 암시 적이거나 명시적일 수 있습니다.
노드는 병렬로 실행되는 것으로 볼 수 있지만 종종 직렬 또는 병렬 처리가 제한적으로 실행됩니다 (예 : 실행하는 스레드가 몇 개있을 수 있음). 유명한 예로 맨체스터 데이터 흐름 시스템 (IIRC)이 태그 데이터 아키텍처를 사용하여 하나 이상의 실행 단위를 통해 그래프의 노드 실행을 예약했습니다. 데이터 흐름 컴퓨팅은 계산 계산을 비동기 적으로 발생시키는 트리거링 계산이 클록 (또는 클럭)에 의해 실행되도록 시도하는 것보다 더 효과적으로 작동하는 상황에 매우 적합합니다.
리 액티브 프로그래밍은이 "캐스케이드 실행"아이디어를 가져 와서 데이터 흐름과 같은 방식으로 프로그램을 생각하는 것처럼 보이지만 일부 노드는 "외부 세계"에 연결되어 있고 이러한 감각이 실행되면 캐스케이드 실행이 트리거됩니다. 같은 노드가 변경됩니다. 프로그램 실행은 복잡한 반사 아크와 유사한 것으로 보입니다. 프로그램은 기본적으로 자극들 사이에서 재채기 일 수도 있고 아닐 수도 있고, 또는 자극들 사이에서 기본적으로 재채기 상태로 정착 될 수도있다.
"비 반응성"프로그래밍은 실행 흐름과 외부 입력과의 관계에 대해 매우 다른 관점에서 프로그래밍하는 것입니다. 사람들은 외부 입력에 반응하는 어떤 것이라도 그들에게 "반응"한다고 말하고 싶은 유혹을받을 것이기 때문에 다소 주관적 일 수 있습니다. 그러나 문제의 정신을 살펴보면 고정 간격으로 이벤트 큐를 폴링하고 함수 (또는 스레드)에있는 이벤트를 디스패치하는 프로그램은 반응성이 떨어집니다 (고정 간격으로 사용자 입력에만 참석하기 때문에). 다시 한 번 말하지만, 이것은 바로 폴링 간격이 빠른 폴링 구현을 매우 낮은 수준의 시스템에 배치하고 그 위에 반응 방식으로 프로그램하는 것을 상상할 수 있습니다.
FRP에 대한 많은 페이지를 읽은 후 마침내 FRP에 대한 이 깨달은 글을 보았고, 마침내 FRP가 무엇에 관한 것인지 이해할 수있었습니다.
나는 아래에 Heinrich Apfelmus (반응 바나나의 저자)를 인용합니다.
기능적 반응성 프로그래밍의 본질은 무엇입니까?
일반적인 대답은“FRP는 변경 가능한 상태 대신 시변 함수 측면에서 시스템을 설명하는 것입니다.”라는 것이 확실합니다. 이것이 의미 론적 관점이다. 그러나 내 의견으로는 다음과 같은 순전히 구문 기준으로 더 깊고 더 만족스러운 답변을 얻을 수 있습니다.
기능적 반응 형 프로그래밍의 본질은 선언시 값의 동적 동작을 완전히 지정하는 것입니다.
예를 들어 카운터의 예를 들어 보면 카운터를 늘리거나 줄이는 데 사용할 수있는“위로”및“아래로”라는 두 개의 단추가 있습니다. 반드시 초기 값을 지정한 다음 버튼을 누를 때마다 변경해야합니다. 이 같은:
counter := 0 -- initial value on buttonUp = (counter := counter + 1) -- change it later on buttonDown = (counter := counter - 1)
요점은 선언시 카운터의 초기 값 만 지정한다는 것입니다. 카운터의 동적 동작은 나머지 프로그램 텍스트에 내재되어 있습니다. 반대로, 기능적 반응 형 프로그래밍은 선언시 다음과 같이 전체 동적 동작을 지정합니다.
counter :: Behavior Int counter = accumulate ($) 0 (fmap (+1) eventUp `union` fmap (subtract 1) eventDown)
카운터의 역학을 이해하고 싶을 때마다 그 정의 만 봐야합니다. 발생할 수있는 모든 것이 오른쪽에 나타납니다. 이는 후속 선언이 이전에 선언 된 값의 동적 동작을 변경할 수있는 명령 방식과는 대조적입니다.
그래서,에 대한 이해 FRP 프로그램은 방정식의 집합입니다 :
j
이산 : 1,2,3,4 ...
f
에 따라 t
이 외부 자극을 모델링 할 수있는 possiblilty을 통합 있도록
프로그램의 모든 상태는 변수로 캡슐화됩니다 x_i
FRP 라이브러리는 진행 시간, 즉을 수행 j
합니다 j+1
.
이 비디오 에서 이러한 방정식을 훨씬 자세히 설명 합니다.
편집하다:
원래 답변 후 약 2 년이 지난 최근에는 FRP 구현에 또 다른 중요한 측면이 있다는 결론에 도달했습니다. 캐시 무효화와 같은 중요한 실제 문제를 해결해야합니다 .
x_i
-s에 대한 방정식 은 종속성 그래프를 나타냅니다. x_i
시간에 변경 사항 중 일부가있을 때 j
다른 x_i'
값 j+1
을 모두 업데이트 할 필요는 없으므로 일부 x_i'
가 독립되어있을 수 있으므로 모든 종속성을 다시 계산할 필요는 없습니다 x_i
.
또한 x_i
변경하는 -s를 증분 업데이트 할 수 있습니다. 예를 들어,의는지도 작업을 생각해 보자 f=g.map(_+1)
스칼라에서 f
하고 g
있는 List
의를 Ints
. 여기 f
에 대응 x_i(t_j)
하고 g
있다 x_j(t_j)
. 이제 요소를 앞에 추가하면의 모든 요소에 대한 작업 g
을 수행하는 것이 낭비 map
입니다 g
. 일부 FRP 구현 (예 : reflex-frp )은이 문제를 해결하는 것을 목표로합니다. 이 문제는 증분 컴퓨팅 이라고도 합니다.
즉, x_i
FRP 의 동작 ( -s)은 캐시 계산으로 간주 될 수 있습니다. x_i
-s 중 일부 f_i
가 변경 되면 이러한 캐시 ( -s) 를 효율적으로 무효화하고 다시 계산하는 것이 FRP 엔진의 임무입니다 .
j+1
" 가없는 . 대신, 연속 시간의 기능을 생각하십시오. Newton, Leibniz 및 다른 사람들이 우리에게 보여 주었 듯이, ODE의 정수와 시스템을 사용하여 이러한 기능을 차등 적이지만 지속적으로 그렇게 묘사하는 것이 종종 매우 편리합니다 (그리고 문자 그대로의 "자연"). 그렇지 않으면 사물 자체 대신 근사 알고리즘 (및 불량 알고리즘)을 설명하고 있습니다.
Conal Elliott ( 직접 PDF , 233KB)의 간단하고 기능적인 반응성 이라는 논문 은 상당히 좋은 소개입니다. 해당 라이브러리도 작동합니다.
종이가 다른 종이로 대체되었습니다. 푸시 풀 기능 반응 형 프로그래밍 ( 직접 PDF , 286KB)으로.
면책 조항 : 내 대답은 Javascript 용 '반응성 프로그래밍'라이브러리 rx.js의 맥락에 있습니다.
함수형 프로그래밍에서는 컬렉션의 각 항목을 반복하는 대신 컬렉션 자체에 고차 함수 (HoF)를 적용합니다. 따라서 FRP의 기본 개념은 각 개별 이벤트를 처리하는 대신 이벤트 스트림 (관측 가능 *으로 구현)을 생성하고 대신 HoF를 적용한다는 것입니다. 이렇게하면 게시자와 가입자를 연결하는 데이터 파이프 라인으로 시스템을 시각화 할 수 있습니다.
Observable 사용의 주요 장점은 다음과 같습니다.
i) 코드에서 상태를 추상화합니다. 예를 들어 이벤트 핸들러가 모든 'n'번째 이벤트에 대해서만 시작되거나 첫 번째 'n'이벤트 후에 실행을 중지하려는 경우, 또는 첫 번째 'n'이벤트 후에 만 발사를 시작하면 카운터 설정, 업데이트 및 확인 대신 HoF (필터, takeUntil, 건너 뛰기)를 사용할 수 있습니다.
ii) 코드 지역성을 향상시킵니다. 구성 요소의 상태를 변경하는 5 개의 다른 이벤트 핸들러가있는 경우, Observable을 병합하고 대신 병합 된 Observable에 단일 이벤트 핸들러를 정의하여 5 개의 이벤트 핸들러를 1로 효과적으로 결합 할 수 있습니다. 전체 시스템의 이벤트가 구성 요소에 영향을 줄 수있는 이벤트에 대해 추론하기 쉽습니다. 모든 이벤트가 단일 처리기에 존재하기 때문입니다.
Iterable은 느리게 소비되는 시퀀스입니다. 각 항목은 사용하고자 할 때마다 반복자가 가져 오기 때문에 열거자는 소비자에 의해 구동됩니다.
Observable은 느리게 생성 된 시퀀스입니다. 각 항목은 시퀀스에 추가 될 때마다 관찰자에게 푸시되므로 열거자는 생산자에 의해 구동됩니다.
야, 이건 정말 멋진 아이디어야! 1998 년에 왜 이것에 대해 알지 못했습니까? 어쨌든, Fran 튜토리얼 에 대한 나의 해석은 다음과 같습니다 . 제안은 가장 환영합니다, 나는 이것을 기반으로 게임 엔진을 시작할 생각입니다.
import pygame
from pygame.surface import Surface
from pygame.sprite import Sprite, Group
from pygame.locals import *
from time import time as epoch_delta
from math import sin, pi
from copy import copy
pygame.init()
screen = pygame.display.set_mode((600,400))
pygame.display.set_caption('Functional Reactive System Demo')
class Time:
def __float__(self):
return epoch_delta()
time = Time()
class Function:
def __init__(self, var, func, phase = 0., scale = 1., offset = 0.):
self.var = var
self.func = func
self.phase = phase
self.scale = scale
self.offset = offset
def copy(self):
return copy(self)
def __float__(self):
return self.func(float(self.var) + float(self.phase)) * float(self.scale) + float(self.offset)
def __int__(self):
return int(float(self))
def __add__(self, n):
result = self.copy()
result.offset += n
return result
def __mul__(self, n):
result = self.copy()
result.scale += n
return result
def __inv__(self):
result = self.copy()
result.scale *= -1.
return result
def __abs__(self):
return Function(self, abs)
def FuncTime(func, phase = 0., scale = 1., offset = 0.):
global time
return Function(time, func, phase, scale, offset)
def SinTime(phase = 0., scale = 1., offset = 0.):
return FuncTime(sin, phase, scale, offset)
sin_time = SinTime()
def CosTime(phase = 0., scale = 1., offset = 0.):
phase += pi / 2.
return SinTime(phase, scale, offset)
cos_time = CosTime()
class Circle:
def __init__(self, x, y, radius):
self.x = x
self.y = y
self.radius = radius
@property
def size(self):
return [self.radius * 2] * 2
circle = Circle(
x = cos_time * 200 + 250,
y = abs(sin_time) * 200 + 50,
radius = 50)
class CircleView(Sprite):
def __init__(self, model, color = (255, 0, 0)):
Sprite.__init__(self)
self.color = color
self.model = model
self.image = Surface([model.radius * 2] * 2).convert_alpha()
self.rect = self.image.get_rect()
pygame.draw.ellipse(self.image, self.color, self.rect)
def update(self):
self.rect[:] = int(self.model.x), int(self.model.y), self.model.radius * 2, self.model.radius * 2
circle_view = CircleView(circle)
sprites = Group(circle_view)
running = True
while running:
for event in pygame.event.get():
if event.type == QUIT:
running = False
if event.type == KEYDOWN and event.key == K_ESCAPE:
running = False
screen.fill((0, 0, 0))
sprites.update()
sprites.draw(screen)
pygame.display.flip()
pygame.quit()
간단히 말해 : 모든 구성 요소를 숫자처럼 취급 할 수 있다면 전체 시스템을 수학 방정식처럼 취급 할 수 있습니다.
Paul Hudak의 저서, Haskell School of Expression 은 Haskell에 대한 훌륭한 소개 일뿐만 아니라 FRP에 상당한 시간을 소비합니다. FRP를 처음 사용하는 사람이라면 FRP의 작동 방식을 이해하는 것이 좋습니다.
Haskell School of Music 이 책 (2011 년판 , 2014 년판 )의 새로운 재 작성도 있습니다.
표시된대로 스프레드 시트처럼 작동합니다. 일반적으로 이벤트 중심 프레임 워크를 기반으로합니다.
모든 "패러다임"과 마찬가지로 최신 성도 논쟁의 여지가 있습니다.
액터의 분산 플로우 네트워크에 대한 나의 경험을 통해 노드 네트워크 전체의 상태 일관성에 대한 일반적인 문제로 쉽게 넘어갈 수 있습니다. 즉, 이상한 루프에서 많은 진동과 트랩으로 끝납니다.
일부 시맨틱은 참조 루프 나 브로드 캐스트를 암시하므로 피하기 어렵고, 액터 네트워크가 예측할 수없는 상태로 수렴 (또는 수렴)하지 않기 때문에 상당히 혼란 스러울 수 있습니다.
마찬가지로, 전체 상태가 솔루션에서 멀어지기 때문에 가장자리가 잘 정의되어 있어도 일부 상태에 도달하지 못할 수 있습니다. 2 + 2가 2가 된 시점과 그들이 그렇게 머물 렀는지 여부에 따라 2 + 2는 4가 될 수도 있고 아닐 수도 있습니다. 스프레드 시트에는 동기식 클럭과 루프 감지 기능이 있습니다. 분산 액터는 일반적으로 그렇지 않습니다.
모든 좋은 재미 :).
FRP에 관한 Clojure subreddit 에서이 멋진 비디오를 발견했습니다. Clojure를 모르더라도 이해하기 쉽습니다.
동영상은 다음과 같습니다. http://www.youtube.com/watch?v=nket0K1RXU4
다음은 동영상이 후반에 참조하는 출처입니다. https://github.com/Cicayda/yolk-examples/blob/master/src/yolk_examples/client/autocomplete.cljs
시간이 지남에 따라 (또는 시간을 무시하면서) 수학적 데이터 변환에 관한 것입니다.
코드에서 이것은 기능적 순도와 선언적 프로그래밍을 의미합니다.
상태 버그는 표준 명령형 패러다임에서 큰 문제입니다. 코드의 다양한 비트는 프로그램 실행에서 다른 "시간"에 일부 공유 상태를 변경할 수 있습니다. 다루기가 어렵다.
FRP에서는 선언적 프로그래밍과 같이 데이터가 한 상태에서 다른 상태로 변환되는 방식과 트리거하는 원인을 설명합니다. 따라서 함수는 단순히 입력에 반응하고 현재 값을 사용하여 새로운 입력을 생성하므로 시간을 무시할 수 있습니다. 이는 상태가 변환 노드의 그래프 (또는 트리)에 포함되며 기능적으로 순수함을 의미합니다.
이것은 복잡성과 디버깅 시간을 크게 줄입니다.
수학에서 A = B + C와 프로그램에서 A = B + C의 차이점을 생각해보십시오. 수학에서 당신은 결코 변하지 않을 관계를 묘사하고 있습니다. 프로그램에서 "지금 바로"A는 B + C라고 말합니다. 그러나 다음 명령은 B ++ 일 수 있으며이 경우 A는 B + C와 동일하지 않습니다. 수학 또는 선언적 프로그래밍에서 A는 요청한 시점에 관계없이 항상 B + C와 같습니다.
따라서 공유 상태의 복잡성을 제거하고 시간이 지남에 따라 값을 변경합니다. 프로그램은 추론하기가 훨씬 쉽습니다.
EventStream은 EventStream + 일부 변형 함수입니다.
동작은 EventStream + 메모리의 일부 값입니다.
이벤트가 발생하면 변환 기능을 실행하여 값이 업데이트됩니다. 이것이 생성하는 값은 동작 메모리에 저장됩니다.
N 개의 다른 행동에 대한 변형 인 새로운 행동을 생성하도록 행동을 구성 할 수 있습니다. 이 구성된 값은 입력 이벤트 (행동)가 발생하면 다시 계산됩니다.
"관찰자는 무국적자이므로 드래그 예제 에서처럼 상태 기계를 시뮬레이션하기 위해 종종 이들 중 몇 개가 필요하다. 우리는 위의 변수 경로와 같이 관련된 모든 관찰자가 접근 할 수있는 상태를 저장해야한다."
견적서-관찰자 패턴의 비추천 http://infoscience.epfl.ch/record/148043/files/DeprecatingObserversTR2010.pdf
Reactive Programming에 대한 짧고 명확한 설명은 Cyclejs-Reactive Programming 에 표시되며 단순하고 시각적 인 샘플을 사용합니다.
[모듈 / 컴포넌트 / 오브젝트] 가 반응 함 이며 외부 이벤트에 반응하여 자체 상태를 관리 할 책임이 있습니다.
이 방법의 장점은 무엇입니까? 그것은이다 제어의 반전 주로하기 때문에 [모듈 / 컴포넌트 / 오브젝트] 대중들에 대한 개인 방법을 사용하여 캡슐화를 개선 자체에 대한 책임이 있습니다.
완전한 지식의 원천이 아닌 좋은 출발점입니다. 거기에서 더 복잡하고 깊은 종이로 넘어갈 수 있습니다.
Rx, Reactive Extensions for .NET을 확인하십시오. 그들은 IEnumerable을 사용하면 기본적으로 스트림에서 '풀링'한다고 지적합니다. IQueryable / IEnumerable에 대한 Linq 쿼리는 집합에서 결과를 '흡입'하는 집합 작업입니다. 그러나 IObservable에 대해 동일한 연산자를 사용하면 '반응하는'Linq 쿼리를 작성할 수 있습니다.
예를 들어 다음과 같은 Linq 쿼리를 작성할 수 있습니다 (mX <100 및 mY <100은 새 Point (mX, mY)를 선택하는 MyObservableSetOfMouseMovements의 m).
Rx 확장 기능을 사용하면 그게 끝입니다. 들어오는 마우스 움직임 스트림에 반응하고 100,100 상자에있을 때마다 그리는 UI 코드가 있습니다 ...
FRP는 기능적 프로그래밍 (모든 것의 아이디어에 기반한 프로그래밍 패러다임은 함수 임)과 반응 형 프로그래밍 패러다임 (모든 것이 스트림 (관측자 및 관찰 가능한 철학)이라는 아이디어에 기반한)의 조합입니다. 그것은 세계 최고의 것입니다.
반응 형 프로그래밍에 대한 Andre Staltz 게시물을 확인하십시오.