Przeczytałem artykuł w Wikipedii na temat programowania reaktywnego . Przeczytałem również mały artykuł na temat programowania reaktywnego . Opisy są dość abstrakcyjne.
- Co w praktyce oznacza funkcjonalne programowanie reaktywne (FRP)?
- Z czego składa się programowanie reaktywne (w przeciwieństwie do programowania niereaktywnego?)?
Moje pochodzenie jest w językach imperatywnych / OO, więc docenione zostanie wyjaśnienie dotyczące tego paradygmatu.
Odpowiedzi:
Jeśli chcesz poznać FRP, możesz zacząć od starego samouczka Fran z 1998 roku, który zawiera animowane ilustracje. W przypadku artykułów zacznij od Functional Reactive Animation, a następnie śledź linki w linku do publikacji na mojej stronie głównej oraz link FRP na wiki Haskell .
Osobiście lubię zastanawiać się, co znaczy FRP , zanim zastanowię się, jak można go wdrożyć. (Kod bez specyfikacji jest odpowiedzią bez pytania i dlatego „nawet nie jest zły”). Nie opisuję FRP w kategoriach reprezentacji / implementacji, jak Thomas K w innej odpowiedzi (wykresy, węzły, krawędzie, odpalanie, wykonanie, itp). Istnieje wiele możliwych stylów implementacji, ale żadna implementacja nie mówi, czym jest FRP .
Rezonuję z prostym opisem Laurence'a G, że FRP dotyczy „typów danych reprezentujących wartość„ w czasie ”. Konwencjonalne programowanie imperatywne rejestruje te wartości dynamiczne tylko pośrednio, poprzez stan i mutacje. Pełna historia (przeszłość, teraźniejszość, przyszłość) nie ma reprezentacji pierwszej klasy. Co więcej, tylko dyskretnie ewoluujące wartości mogą być (pośrednio) uchwycone, ponieważ imperatywny paradygmat jest tymczasowo dyskretny. W przeciwieństwie do tego FRP rejestruje te ewoluujące wartości bezpośrednio i nie ma trudności z ciągłą ewolucją wartości.
FRP jest również niezwykły, ponieważ jest zbieżny bez obawy o teoretyczne i pragmatyczne gniazdo szczurów, które nęka imperatywną współbieżność. Semantycznie współbieżność FRP jest drobnoziarnista , zdeterminowana i ciągła . (Mówię o znaczeniu, a nie implementacji. Implementacja może, ale nie musi, obejmować współbieżność lub paralelizm). Określenie semantyczne jest bardzo ważne dla rozumowania, zarówno rygorystycznego, jak i nieformalnego. Podczas gdy współbieżność powoduje ogromną złożoność programowania imperatywnego (z powodu niedeterministycznego przeplatania), w FRP jest on łatwy.
Czym jest FRP? Mógłbyś to sam wymyślić. Zacznij od tych pomysłów:
Wartości dynamiczne / ewoluujące (tj. Wartości „w czasie”) same w sobie są wartościami pierwszej klasy. Możesz je definiować i łączyć, przekazywać i wyłączać z funkcji. Nazwałam te rzeczy „zachowaniami”.
Zachowania budowane są z kilku prymitywów, takich jak stałe (statyczne) zachowania i czas (jak zegar), a następnie kombinacja sekwencyjna i równoległa. n zachowań łączy się, stosując funkcję n-ary (na wartościach statycznych), „punktowo”, tj. ciągle w czasie.
Aby uwzględnić zjawiska dyskretne, należy mieć inny typ (rodzinę) „zdarzeń”, z których każde ma strumień (skończony lub nieskończony). Każde wystąpienie ma powiązany czas i wartość.
Aby wymyślić słownictwo kompozytorskie, z którego można zbudować wszystkie zachowania i zdarzenia, zagraj z kilkoma przykładami. Rozbijaj dalej na części, które są bardziej ogólne / proste.
Abyś wiedział, że jesteś na solidnym gruncie, nadaj całemu modelowi podstawę kompozycyjną, używając techniki semantyki denotacyjnej, co oznacza po prostu, że (a) każdy typ ma odpowiadający prosty i precyzyjny matematyczny typ „znaczeń” oraz ( b) każdy prymityw i operator ma proste i precyzyjne znaczenie w zależności od znaczeń składników. Nigdy nie mieszaj kwestii związanych z implementacją z procesem eksploracji. Jeśli ten opis jest bełkotliwy, skonsultuj się z (a) Projektem denotacyjnym z morfizmami klas typu , (b) Funkcjonalnym programowaniem reaktywnym push-pull (ignorując bity implementacyjne) oraz (c) stroną Wikipedii Denotational Semantics Haskell. Strzeż się, że semantyka denotacyjna składa się z dwóch części, od jej dwóch założycieli, Christophera Stracheya i Dany Scott: łatwiejszej i bardziej użytecznej części Strachey oraz trudniejszej i mniej użytecznej (do projektowania oprogramowania) części Scott.
Jeśli będziesz przestrzegać tych zasad, spodziewam się, że dostaniesz coś mniej więcej w duchu FRP.
Skąd wziąłem te zasady? W projektowaniu oprogramowania zawsze zadaję to samo pytanie: „co to znaczy?”. Semantyka denotacyjna dała mi dokładne ramy dla tego pytania i takie, które pasują do mojej estetyki (w przeciwieństwie do semantyki operacyjnej lub aksjomatycznej, które pozostawiają mnie niezadowoloną). Więc zadałem sobie pytanie, co to jest zachowanie? Wkrótce zdałem sobie sprawę, że czasowo dyskretna natura obliczeń imperatywnych jest dostosowaniem do określonego stylu maszyny , a nie naturalnym opisem samego zachowania. Najprostszy precyzyjny opis zachowań, jaki mogę wymyślić, to po prostu „funkcja (ciągłego) czasu”, więc to mój model. Cudownie, ten model obsługuje ciągłą, deterministyczną współbieżność z łatwością i wdziękiem.
Prawidłowe i wydajne wdrożenie tego modelu było dużym wyzwaniem, ale to już inna historia.
źródło
W czystym programowaniu funkcjonalnym nie ma skutków ubocznych. W przypadku wielu rodzajów oprogramowania (na przykład cokolwiek z interakcją użytkownika) działania niepożądane są konieczne na pewnym poziomie.
Jednym ze sposobów uzyskania efektu podobnego do efektu ubocznego przy jednoczesnym zachowaniu funkcjonalnego stylu jest zastosowanie funkcjonalnego programowania reaktywnego. Jest to połączenie programowania funkcjonalnego i programowania reaktywnego. (Artykuł w Wikipedii, do którego linkujesz, dotyczy tego drugiego.)
Podstawową ideą programowania reaktywnego jest to, że istnieją pewne typy danych, które reprezentują wartość „w czasie”. Obliczenia obejmujące te wartości zmieniające się w czasie same będą miały wartości, które zmieniają się w czasie.
Na przykład, możesz przedstawić współrzędne myszy jako parę liczb całkowitych w czasie. Powiedzmy, że mieliśmy coś takiego (to jest pseudo-kod):
W dowolnym momencie xiy miałyby współrzędne myszy. W przeciwieństwie do programowania niereaktywnego, musimy przypisać to zadanie tylko raz, a zmienne xiy pozostaną „aktualne” automatycznie. Dlatego programowanie reaktywne i programowanie funkcjonalne działają tak dobrze razem: programowanie reaktywne eliminuje potrzebę mutacji zmiennych, jednocześnie pozwalając ci robić wiele z tego, co można osiągnąć dzięki mutacjom zmiennych.
Jeśli następnie wykonamy pewne obliczenia na tej podstawie, wówczas otrzymane wartości będą również wartościami, które zmieniają się w czasie. Na przykład:
W tym przykładzie
minX
zawsze będzie o 16 mniej niż współrzędna x wskaźnika myszy. Za pomocą bibliotek świadomych reaktywnie możesz powiedzieć coś takiego:Wokół wskaźnika myszy zostanie narysowane pole o wymiarach 32 x 32, które będzie śledzić go w dowolnym miejscu.
Oto całkiem niezły artykuł na temat programowania funkcjonalnego .
źródło
sqrt(x)
C z twoim makrem, to po prostu obliczasqrt(mouse_x())
i daje mi podwójne. W prawdziwym funkcjonalnym systemie reaktywnymsqrt(x)
zwróciłby nowe „podwójne z czasem”. Jeśli spróbujesz symulować system FR,#define
będziesz musiał przysiąc zmienne na korzyść makr. Systemy FR zazwyczaj również ponownie obliczają rzeczy tylko wtedy, gdy trzeba je ponownie obliczyć, podczas gdy używanie makr oznaczałoby, że ciągle dokonujesz ponownej oceny wszystkiego, aż do podwyrażeń.Łatwym sposobem osiągnięcia pierwszej intuicji na temat tego, jak to jest, jest wyobrażenie sobie, że twój program jest arkuszem kalkulacyjnym, a wszystkie zmienne są komórkami. Jeśli dowolna komórka w arkuszu kalkulacyjnym ulegnie zmianie, zmieniają się również wszystkie komórki, które odnoszą się do tej komórki. Tak samo jest z FRP. Teraz wyobraź sobie, że niektóre komórki zmieniają się same (a raczej są pobierane ze świata zewnętrznego): w sytuacji GUI, pozycja myszy byłaby dobrym przykładem.
To niekoniecznie bardzo tęskni. Metafora rozpada się dość szybko, kiedy faktycznie używasz systemu FRP. Po pierwsze, zwykle próbuje się również modelować zdarzenia dyskretne (np. Kliknięcie myszą). Kładę to tutaj, aby dać ci wyobrażenie, jak to jest.
źródło
Dla mnie jest to około 2 różnych znaczeń symbolu
=
:x = sin(t)
oznacza, żex
jest inna nazwa dlasin(t)
. Więc pisaniex + y
jest tym samymsin(t) + y
. Pod tym względem funkcjonalne programowanie reaktywne przypomina matematykę: jeśli piszeszx + y
, jest ono obliczane na podstawie dowolnej wartościt
w momencie jego użycia.x = sin(t)
jest przypisanie: oznacza, żex
przechowuje wartośćsin(t)
wziętą w momencie przypisania.źródło
x = sin(t)
oznaczax
wartośćsin(t)
dla danegot
. To nie inna nazwasin(t)
w funkcji. W przeciwnym razie byłobyx(t) = sin(t)
.2 + 3 = 5
luba**2 + b**2 = c**2
.OK, z wiedzy w tle i po przeczytaniu strony w Wikipedii, na którą wskazałeś, wydaje się, że programowanie reaktywne przypomina obliczanie przepływu danych, ale z określonymi zewnętrznymi „bodźcami” wyzwalającymi zestaw węzłów do uruchamiania i wykonywania ich obliczeń.
Jest to dość dobrze dostosowane do projektu interfejsu użytkownika, na przykład w którym dotknięcie kontrolki interfejsu użytkownika (powiedzmy, regulacji głośności w aplikacji do odtwarzania muzyki) może wymagać aktualizacji różnych elementów wyświetlania i rzeczywistej głośności wyjścia audio. Gdy zmodyfikujesz głośność (powiedzmy suwak), która odpowiada modyfikacji wartości powiązanej z węzłem na ukierunkowanym wykresie.
Różne węzły posiadające krawędzie z tego węzła „wartość objętości” byłyby automatycznie uruchamiane, a wszelkie niezbędne obliczenia i aktualizacje naturalnie falowałyby przez aplikację. Aplikacja „reaguje” na bodziec użytkownika. Funkcjonalne programowanie reaktywne byłoby po prostu implementacją tego pomysłu w funkcjonalnym języku lub ogólnie w funkcjonalnym paradygmacie programowania.
Aby uzyskać więcej informacji na temat „przetwarzania danych”, wyszukaj te dwa słowa w Wikipedii lub użyj swojej ulubionej wyszukiwarki. Ogólna idea jest następująca: program jest ukierunkowanym wykresem węzłów, z których każdy wykonuje pewne proste obliczenia. Węzły te są połączone ze sobą za pomocą łączy graficznych, które zapewniają wyjścia niektórych węzłów z wejściami innych.
Gdy węzeł odpala lub wykonuje obliczenia, węzły podłączone do jego wyjść mają odpowiadające im wejścia „wyzwalane” lub „oznaczone”. Każdy węzeł posiadający wszystkie wejścia wyzwolone / oznaczone / dostępne automatycznie uruchamia się. Wykres może być niejawny lub jawny w zależności od tego, w jaki sposób wdrażane jest programowanie reaktywne.
Węzły można traktować jako odpalane równolegle, ale często są one wykonywane szeregowo lub z ograniczoną równoległością (na przykład może być wykonywanych przez kilka wątków). Słynny przykład to Manchester Dataflow Machine , która (IIRC) zastosowała oznakowaną architekturę danych do zaplanowania wykonania węzłów na wykresie przez jedną lub więcej jednostek wykonawczych. Obliczenia przepływu danych są dość dobrze dostosowane do sytuacji, w których wyzwalanie obliczeń asynchronicznie, powodujące kaskady obliczeń, działa lepiej niż próba kierowania wykonaniem zegarem (lub zegarami).
Programowanie reaktywne importuje tę ideę „kaskady wykonania” i wydaje się, że myśli o programie w sposób podobny do przepływu danych, ale pod warunkiem, że niektóre węzły są podłączone do „świata zewnętrznego”, a kaskady wykonania są uruchamiane, gdy te sensoryczne podobne zmiany węzłów. Wykonanie programu wyglądałoby wówczas jak coś analogicznego do złożonego łuku refleksowego. Program może, ale nie musi, być w zasadzie bezczynny między bodźcami lub może zasadniczo ustabilizować się pomiędzy bodźcami.
programowanie „niereaktywne” byłoby programowaniem z zupełnie innym spojrzeniem na przepływ wykonania i związek z zewnętrznymi danymi wejściowymi. To może być nieco subiektywne, ponieważ ludzie będą skłonni powiedzieć wszystko, co reaguje na zewnętrzne sygnały wejściowe „reaguje” na nie. Ale patrząc na ducha tej rzeczy, program, który odpytuje kolejkę zdarzeń w ustalonym odstępie czasu i wywołuje wszelkie zdarzenia znalezione w funkcjach (lub wątkach), jest mniej reaktywny (ponieważ bierze udział tylko w danych wprowadzanych przez użytkownika w ustalonych odstępach czasu). Ponownie, jest to sedno sprawy: można sobie wyobrazić umieszczenie implementacji odpytywania z szybkim interwałem odpytywania w systemie na bardzo niskim poziomie i programowanie na nim reaktywnie.
źródło
Po przeczytaniu wielu stron o FRP w końcu natknąłem się na to oświecające pismo o FRP, w końcu zrozumiałem, na czym tak naprawdę polega FRP.
Cytuję poniżej Heinricha Apfelmusa (autora reaktywnego banana).
Tak więc, moim zdaniem, program FRP jest zbiorem równań:
j
jest dyskretny: 1,2,3,4 ...f
zależy odt
tego, co obejmuje możliwość modelowania bodźców zewnętrznychcały stan programu jest zamknięty w zmiennych
x_i
Biblioteka FRP dba o postęp czasu, innymi słowy,
j
doj+1
.Wyjaśniam te równania bardziej szczegółowo w tym filmie.
EDYTOWAĆ:
Około 2 lata po oryginalnej odpowiedzi doszedłem niedawno do wniosku, że implementacje FRP mają jeszcze jeden ważny aspekt. Muszą (i zwykle robią) rozwiązać ważny problem praktyczny: unieważnienie pamięci podręcznej .
Równania dla
x_i
-s opisują wykres zależności. Kiedy niektórex_i
zmiany w danym momencie,j
nie wszystkie pozostałex_i'
wartościj+1
muszą zostać zaktualizowane, więc nie wszystkie zależności muszą zostać ponownie obliczone, ponieważ niektórex_i'
mogą być niezależnex_i
.Ponadto
x_i
-s, które się zmieniają, można stopniowo aktualizować. Dla przykładu rozważmy operację mapęf=g.map(_+1)
w Scala, gdzief
ig
sąList
odInts
. Tutajf
odpowiadax_i(t_j)
ig
jestx_j(t_j)
. Teraz, jeśli przygotuję do tego elementg
, byłoby niepotrzebnie przeprowadzićmap
operację dla wszystkich elementów wg
. Niektóre implementacje FRP (na przykład reflex-frp ) mają na celu rozwiązanie tego problemu. Ten problem jest również znany jako obliczanie przyrostowe.Innymi słowy, zachowania (
x_i
-s) we FRP można traktować jako obliczenia buforowane. Mechanizm FRP ma za zadanie skutecznie unieważnić i ponownie obliczyć te pamięci podręczne (x_i
-y), jeśli niektóre zf_i
nich się zmienią.źródło
j+1
”. Zamiast tego pomyśl o funkcjach ciągłego czasu. Jak pokazali nam Newton, Leibniz i inni, często bardzo przydatne (i „naturalne” w dosłownym znaczeniu) jest opisanie tych funkcji w różny sposób, ale w sposób ciągły, przy użyciu całek i układów ODE. W przeciwnym razie opisujesz algorytm aproksymacji (i kiepski) zamiast samej rzeczy.Artykuł Po prostu wydajna reaktywność funkcjonalna Conal Elliott ( bezpośredni PDF , 233 KB) jest dość dobrym wprowadzeniem. Odpowiednia biblioteka również działa.
Dokument został zastąpiony przez inny papier, funkcjonalne programowanie reaktywne Push-pull ( bezpośredni PDF , 286 KB).
źródło
Zastrzeżenie: moja odpowiedź jest w kontekście rx.js - biblioteki „programowania reaktywnego” dla Javascript.
W programowaniu funkcjonalnym zamiast iteracji po każdym elemencie kolekcji, stosujesz funkcje wyższego rzędu (HoF) do samej kolekcji. Zatem idea FRP polega na tym, że zamiast przetwarzać każde pojedyncze zdarzenie, utwórz strumień zdarzeń (zaimplementowany z możliwym do zaobserwowania *) i zastosuj do tego HoF. W ten sposób możesz wizualizować system jako potoki danych łączące wydawców z subskrybentami.
Głównymi zaletami używania obserwowalnego są:
i) abstrahowanie stanu od twojego kodu, np. Jeśli chcesz, aby moduł obsługi zdarzeń był uruchamiany tylko dla każdego n-tego zdarzenia lub przestał strzelać po pierwszych zdarzeniach „n”, lub zacznij strzelać dopiero po pierwszych zdarzeniach „n”, możesz po prostu użyć HoF (odpowiednio filtr, takeUntil, pomiń) zamiast ustawiania, aktualizowania i sprawdzania liczników.
ii) poprawia lokalizację kodu - jeśli masz 5 różnych procedur obsługi zdarzeń zmieniających stan komponentu, możesz scalić ich obserwowalne i zdefiniować jedną procedurę obsługi zdarzeń na scalonej obserwowalnej zamiast tego, skutecznie łącząc 5 procedur obsługi zdarzeń w 1. To sprawia, że jest to bardzo łatwo zrozumieć, jakie zdarzenia w całym systemie mogą wpłynąć na komponent, ponieważ wszystkie są obecne w jednym module obsługi.
Iterable to leniwie zużyta sekwencja - każdy element jest ciągnięty przez iterator, ilekroć chce go użyć, a zatem wyliczenie jest sterowane przez konsumenta.
Obserwowalna jest leniwie wytwarzana sekwencja - każdy przedmiot jest wypychany do obserwatora za każdym razem, gdy jest dodawany do sekwencji, a zatem wyliczenie jest sterowane przez producenta.
źródło
Koleś, to cholernie genialny pomysł! Dlaczego nie dowiedziałem się o tym w 1998 roku? Tak czy inaczej, oto moja interpretacja samouczka Fran . Sugestie są mile widziane, myślę o uruchomieniu silnika gry opartego na tym.
W skrócie: Jeśli każdy element można traktować jak liczbę, cały system można traktować jak równanie matematyczne, prawda?
źródło
Książka Paula Hudaka, The Haskell School of Expression , jest nie tylko świetnym wprowadzeniem do Haskell, ale także spędza sporo czasu na FRP. Jeśli dopiero zaczynasz przygodę z FRP, gorąco polecam, abyś wiedział, jak działa FRP.
Jest też coś, co wygląda jak nowe przepisanie tej książki (wydanej w 2011 r., Zaktualizowanej w 2014 r.), The Haskell School of Music .
źródło
Zgodnie z poprzednimi odpowiedziami wydaje się, że matematycznie myślimy po prostu w wyższej kolejności. Zamiast myśleć o wartości x mającej typ X , myślimy o funkcji x : T → X , gdzie T jest rodzajem czasu, czy to liczbami naturalnymi, liczbami całkowitymi czy kontinuum. Teraz, gdy piszemy y : = x + 1 w języku programowania, faktycznie mamy na myśli równanie y ( t ) = x ( t ) + 1.
źródło
Jak wspomniano, działa jak arkusz kalkulacyjny. Zwykle oparty na frameworku sterowanym zdarzeniami.
Jak w przypadku wszystkich „paradygmatów”, jego nowość jest dyskusyjna.
Z mojego doświadczenia z rozproszonymi przepływami aktorów, może łatwo paść ofiarą ogólnego problemu spójności stanu w sieci węzłów, tj. Kończy się to dużą oscylacją i pułapką w dziwnych pętlach.
Trudno tego uniknąć, ponieważ niektóre semantyki sugerują pętle referencyjne lub transmisje, i mogą być dość chaotyczne, ponieważ sieć aktorów zbiega się (lub nie) w jakimś nieprzewidywalnym stanie.
Podobnie niektóre stany mogą nie zostać osiągnięte, mimo że mają dobrze zdefiniowane krawędzie, ponieważ stan globalny odwraca się od rozwiązania. 2 + 2 może, ale nie musi, wynosić 4, w zależności od tego, kiedy 2 stało się 2 i czy tak pozostały. Arkusze kalkulacyjne mają synchroniczne zegary i wykrywanie pętli. Rozproszeni aktorzy na ogół nie.
Cała dobra zabawa :).
źródło
Znalazłem ten fajny film na subreddicie Clojure o FRP. Łatwo to zrozumieć, nawet jeśli nie znasz Clojure.
Oto wideo: http://www.youtube.com/watch?v=nket0K1RXU4
Oto źródło, do którego odwołuje się wideo w drugiej połowie: https://github.com/Cicayda/yolk-examples/blob/master/src/yolk_examples/client/autocomplete.cljs
źródło
Ten artykuł Andre Staltza jest najlepszym i najbardziej zrozumiałym wyjaśnieniem, jakie do tej pory widziałem.
Niektóre cytaty z artykułu:
Oto przykład fantastycznych diagramów, które są częścią tego artykułu:
źródło
Chodzi o matematyczne transformacje danych w czasie (lub ignorowanie czasu).
W kodzie oznacza to czystość funkcjonalną i programowanie deklaratywne.
Błędy stanu są ogromnym problemem w standardowym paradygmacie imperatywu. Różne fragmenty kodu mogą zmieniać stan współdzielenia w różnych „momentach” podczas wykonywania programów. Trudno sobie z tym poradzić.
We FRP opisujesz (jak w programowaniu deklaratywnym), w jaki sposób dane przekształcają się z jednego stanu do drugiego i co je wyzwala. Pozwala to zignorować czas, ponieważ twoja funkcja po prostu reaguje na dane wejściowe i wykorzystuje ich bieżące wartości do utworzenia nowej. Oznacza to, że stan jest zawarty na wykresie (lub drzewie) węzłów transformacji i jest funkcjonalnie czysty.
To znacznie zmniejsza złożoność i czas debugowania.
Pomyśl o różnicy między A = B + C w matematyce i A = B + C w programie. W matematyce opisujesz związek, który nigdy się nie zmieni. W programie jest napisane, że „W tej chwili” A to B + C. Ale następnym poleceniem może być B ++, w którym to przypadku A nie jest równe B + C. W matematyce lub programowaniu deklaratywnym A zawsze będzie równe B + C, bez względu na to, o który moment poprosisz.
Usuwając złożoność wspólnego stanu i zmieniając wartości w czasie. Twój program jest o wiele łatwiejszy do uzasadnienia.
EventStream to EventStream + jakaś funkcja transformacji.
Zachowanie to EventStream + Pewna wartość w pamięci.
Po uruchomieniu zdarzenia wartość jest aktualizowana przez uruchomienie funkcji transformacji. Wytworzona wartość jest przechowywana w pamięci zachowań.
Zachowania można komponować w celu uzyskania nowych zachowań, które są transformacją N innych zachowań. Ta skomponowana wartość zostanie ponownie obliczona podczas uruchamiania zdarzeń wejściowych (zachowań).
„Ponieważ obserwatorzy są bezstanowi, często potrzebujemy kilku z nich, aby symulować maszynę stanów, jak w przykładzie przeciągania. Musimy zapisać stan, w którym jest dostępny dla wszystkich zaangażowanych obserwatorów, na przykład na ścieżce zmiennej powyżej”.
Cytat z - Przestarzałe wzorce obserwatora http://infoscience.epfl.ch/record/148043/files/DeprecatingObserversTR2010.pdf
źródło
Krótkie i jasne wyjaśnienie dotyczące programowania reaktywnego pojawia się w Cyclejs - Programowanie reaktywne , wykorzystuje proste i wizualne próbki.
To dobry punkt startowy, a nie pełne źródło wiedzy. Stamtąd możesz przejść do bardziej złożonych i głębokich dokumentów.
źródło
Sprawdź Rx, Reactive Extensions dla .NET. Wskazują, że w IEnumerable w zasadzie „wyciągasz” ze strumienia. Zapytania Linq nad IQueryable / IEnumerable to operacje na zestawach, które „wysysają” wyniki z zestawu. Ale z tymi samymi operatorami w IObservable możesz pisać zapytania Linq, które „reagują”.
Na przykład, możesz napisać zapytanie Linq jak (z mw MyObservableSetOfMouseMovements, gdzie mX <100 i mY <100 wybierz nowy punkt (mX, mY)).
a dzięki rozszerzeniom Rx to wszystko: masz kod interfejsu, który reaguje na nadchodzący strumień ruchów myszy i rysuje, gdy jesteś w polu 100 100 ...
źródło
FRP to połączenie programowania funkcjonalnego (paradygmat programowania zbudowany na idei wszystkiego jest funkcją) i reaktywnego paradygmatu programowania (zbudowany na idei, że wszystko jest strumieniem (obserwator i obserwowalna filozofia)). To ma być najlepszy ze światów.
Na początek sprawdź post Andre Andreta na temat programowania reaktywnego.
źródło