Frage

Ich habe gelesen, die Wikipedia-Artikel auf reaktive Programmierung.Ich habe auch gelesen das kleine Artikel auf funktionale reaktive Programmierung.Die Beschreibungen sind sehr Abstrakt.

  1. Was ist funktionale reaktive Programmierung (FRP) in der Praxis bedeuten?
  2. Was bedeutet reaktive Programmierung (im Gegensatz zu nicht-reaktive Programmierung?) bestehen?

Mein hintergrund ist in imperative/OO-Sprachen, also eine Erklärung, die sich auf dieses Paradigma würde werden geschätzt.

War es hilfreich?

Lösung

Wenn Sie ein Gefühl für FRP erhalten möchten, können Sie mit dem alten beginnen Fran Tutorial von 1998, die animierten Illustrationen hat. Für Papiere, beginnen Sie mit Functional Reactive-Animation und dann auf Links folgen auf die Veröffentlichungen Link auf meiner Homepage und der FRP Link auf der Haskell Wiki .

Persönlich Ich mag denken über das, was FRP Mittel vor Adressierung, wie sie umgesetzt werden könnten. (-Code ohne Angabe ist eine Antwort ohne Frage und damit „nicht einmal falsch“.) So beschreibe ich nicht FRP in Darstellung / Implementierung Begriffe wie Thomas K hat in einer anderen Antwort (Graphen, Knoten, Kanten, Brennen, Ausführung, etc.). Es gibt viele mögliche Implementierung von Designs, aber keine Implementierung sagt, was FRP ist .

Ich Resonanz mit Laurence G einfacher Beschreibung, die FRP über „Datentypen, die einen Wert‚im Laufe der Zeit‘darstellen“ ist. Herkömmliche imperativen Programmierung erfasst diese dynamischen Werte nur indirekt, durch staatliche und Mutationen. Die komplette Geschichte (Vergangenheit, Gegenwart, Zukunft) hat keine erstklassige Darstellung. Darüber hinaus wird nur diskret entwickelt Werte (indirekt) erfasst werden, da der Imperativ Paradigma zeitlich diskret ist. Im Gegensatz dazu nimmt FRP diese sich entwickelnden Werte direkt und hat keine Schwierigkeiten mit kontinuierlich entwickeln Werte.

FRP ist auch ungewöhnlich, dass es ohne Lauf afoul der theoretischen und pragmatischen Ratten Nest gleichzeitig ist die zwingend notwendig Gleichzeitigkeit plagt. Semantisch Gleichzeitigkeit des FRP ist feinkörnige bestimmt und kontinuierliche . (Ich spreche von Bedeutung, nicht Implementierung. Eine Implementierung kann oder nicht Gleichzeitigkeit oder Parallelität beinhalten kann.) Semantic Determiniert ist sehr wichtig für die Argumentation, sowohl strenge und informell. Während Parallelität enorme Komplexität zu imperativen Programmierung (durch nichtdeterministische Verschachtelung) fügt hinzu, es ist mühelos in FRP.

Also, was ist FRP? Sie hätten es selbst erfunden. Beginnen Sie mit diesen Ideen:

  • Dynamisch / entwickelnden Werte (das heißt, Werte „über die Zeit“) sind erstklassige Werte in sich. Sie können sie definieren und kombinieren sie, geben sie in & out von Funktionen. Ich nannte diese Dinge "Verhalten".

  • Behaviors sind aus wenigen Grundelementen, wie konstant (statisch) Verhalten und Zeit (wie eine Uhr) und dann mit sequentiellen und parallelen Kombination aufgebaut. n Verhalten durch Anlegen einer n-ary-Funktion (auf der statischen Werte) kombiniert werden, "punktweise", das heißt, kontinuierlich über die Zeit.

  • Um einzelne Phänomene zu erklären, haben eine andere Art (Familie) von „Ereignissen“, von denen jeder einen Strom (endlich oder unendlich) von Vorkommen hat. Jedes Vorkommen hat eine zugehörige Zeit und Wert.

  • , um mit dem kompositorischen Vokabular aus dem alle Verhaltensweisen und Ereignisse können gebaut werden, mit einigen Beispielen spielen. Halten Sie in Stücke zu dekonstruieren, die allgemeinere / einfach.

  • Damit Sie wissen, dass Sie auf festen Boden sind, gibt dem ganze Modell eine kompositorische Grundlage, die Technik der denotational Semantik, das nur bedeutet, dass (a) jede Art eine entsprechende einfache und genaue mathematische Art hat „Bedeutungen“ ist, und (b) jedes Grundelement und Operator hat eine einfache und genaue Bedeutung in Abhängigkeit von den Bedeutungen der Bestandteile. Nie, nie Implementierung Überlegungen in die Exploration Prozess mischen. Wenn diese Beschreibung Kauderwelsch Sie ist, fragen Sie (a) Denotationelle Design mit Typ-Klasse morphisms , (b) Push-Pull-funktionelle reaktive Programmierung (ohne Berücksichtigung der Implementierung Bits), und (c) die denotationelle Semantics Haskell wikibooks Beachten Sie, dass denotational Semantik hat zwei Teile, von seinen beiden Gründer Christopher Strachey und Dana Scott. desto einfacher & more nützlich Strachey Teil und der härter und weniger nützlich (für Software-Design) Scott Teil.

Wenn Sie mit diesen Prinzipien festhalten, ich erwarte, dass Sie etwas bekommen mehr oder weniger im Geist des FRP.

Wo habe ich diese Prinzipien? In der Software-Design, frage ich immer die gleiche Frage: „Was bedeutet es“. Denotationelle Semantik gab mir einen präzisen Rahmen für diese Frage, und eine, die meine Ästhetik paßt (im Gegensatz zu operativer oder axiomatischer Semantik, von denen beide mir verläßt unzufrieden). Also habe ich mich gefragt, was Verhalten ist? Ich erkennen bald, dass die zeitlich diskrete Natur zwingender Berechnung ist eine Unterkunft zu einem bestimmten Stil von Maschine , anstatt eine natürliche Beschreibung des Verhaltens selbst. Die einfachste genaue Beschreibung des Verhaltens ich denken kann, ist einfach „Funktion (kontinuierlich) Zeit“, so dass mein Modell ist. Herrlich, Griffe dieses Modell kontinuierlich, determinis Parallelität mit Leichtigkeit und Anmut.

Es ist schon eine ziemliche Herausforderung, dieses Modell korrekt umzusetzen und effizient, aber das ist eine andere Geschichte.

Andere Tipps

In der reinen funktionaler Programmierung gibt es keine Nebenwirkungen. Für viele Arten von Software (zum Beispiel etwas mit Benutzer-Interaktion) Nebenwirkungen sind zu einem gewissen Grad notwendig.

Eine Möglichkeit, Nebenwirkung wie Verhalten zu bekommen, während immer noch einen funktionellen Stil zu binden, ist funktionelle reaktive Programmierung zu verwenden. Dies ist die Kombination der funktionalen Programmierung und Reaktive Programmierung. (Wikipedia-Artikel Sie verknüpft ist über diese.)

Die Grundidee hinter reaktiver Programmierung ist, dass es bestimmte Datentypen, die einen Wert „im Laufe der Zeit“ darstellen. Berechnungen, die diese Veränderung über Zeit Werte werden sich Werte, die im Laufe der Zeit ändern.

beinhalten

Zum Beispiel könnten Sie die Maus repräsentieren Koordinaten als ein Paar von integer-über-Zeit-Werten. Nehmen wir an, wir hatten so etwas wie (dies ist Pseudo-Code):

x = <mouse-x>;
y = <mouse-y>;

Zu jedem Zeitpunkt, x und y würden die Koordinaten der Maus haben. Im Gegensatz zu nicht-reaktiver Programmierung, brauchen wir nur diese Zuordnung einmal zu machen, und die x- und y-Variablen bleiben „up to date“ automatisch. Aus diesem Grunde reaktive Programmierung und funktionale Programmierung arbeitet so gut zusammen. Reaktive Programmierung die Notwendigkeit beseitigt Variablen zu mutieren, während immer noch so dass Sie eine Menge tun, was Sie mit variablen Mutationen erreichen könnten

Wenn wir dann einige Berechnungen tun auf der Grundlage dieser die daraus resultierenden Werte werden auch Werte sein, die im Laufe der Zeit ändern. Zum Beispiel:

minX = x - 16;
minY = y - 16;
maxX = x + 16;
maxY = y + 16;

In diesem Beispiel minX immer 16 kleiner sein als die x des Mauszeigers koordinieren. Mit reaktiven bewussten Bibliotheken können Sie dann sagen, so etwas wie:

rectangle(minX, minY, maxX, maxY)

Und ein 32x32-Box wird um den Mauszeiger gezogen werden und wird sie verfolgen, wo immer sie sich bewegt.

Dies ist eine ziemlich gute Papier auf funktionelle reaktive Programmierung .

Eine einfache Möglichkeit, eine erste Intuition zu erreichen, wie es ist Ihr Programm ist, sich vorzustellen, ist eine Tabelle und alle Ihre Variablen sind Zellen. Wenn eine der Zellen in einer Tabelle ändern, beliebigen Zellen, die auch zu dieser Zelle Änderung beziehen. Es ist genau das gleiche mit FRP. Nun stell dir vor, dass einige der Zellen auf ihrem eigenen ändern (oder besser gesagt, sind von der Außenwelt genommen.): in einer GUI-Situation, die Position der Maus wäre ein gutes Beispiel sein

Das notwendigerweise verpasst ziemlich viel. Die Metapher bricht ziemlich schnell ab, wenn Sie tatsächlich ein FRP-System. Zum einen gibt es in der Regel auch diskrete Ereignisse zu modellieren versucht (beispielsweise die Maus angeklickt wird). Ich bin das nur hier setzen Sie eine Idee zu geben, wie es ist.

Für mich ist es etwa 2 verschiedene Bedeutungen des Symbols =:

  1. In der Mathematik x = sin(t) bedeutet, dass x ist andere Namen für sin(t). So schreibt x + y ist das gleiche wie sin(t) + y. Funktionale reaktive Programmierung ist wie Mathematik in dieser Hinsicht., Wenn Sie x + y schreiben, wird er berechnet mit dem, was der Wert von t zu der Zeit ist es verwendet
  2. In C-ähnlichen Programmiersprachen (imperative Sprachen), x = sin(t) ist eine Aufgabe: es bedeutet, dass x speichert der Wert sin(t) zum Zeitpunkt der Zuweisung genommen
  3. .

OK, von Hintergrundwissen und sich beim Lesen der Wikipedia-Seite, auf die Sie zeigte, scheint es, dass reaktive Programmierung ist so etwas wie Datenfluß Computing, sondern mit bestimmten externen „Stimuli“ Auslösen einer Menge von Knoten ihre Berechnungen zu feuern und durchzuführen.

Das ist ziemlich gut für UI-Design, zum Beispiel, bei dem eine Steuerung der Benutzeroberfläche berührt (zum Beispiel die Lautstärke auf einer Wiedergabe von Musik-Anwendung) müssen möglicherweise verschiedene Anzeigeelemente und das tatsächliche Volumen der Audioausgabe aktualisieren. Wenn Sie die Lautstärke ändern (einen Schieberegler, sagen wir mal), die auf die Änderung des Wertes in Verbindung mit einem Knoten in einem gerichteten Graphen entsprechen würde.

verschiedene Knoten mit Kanten von diesem „Volumenwert“ Node automatisch ausgelöst werden würden, und notwendige Berechnungen und Aktualisierungen würden die Anwendung natürlich Welligkeit durch. Die Anwendung „reagiert“ auf die Benutzerstimulus. Funktionale reaktive Programmierung wäre nur die Umsetzung dieser Idee in einer funktionalen Sprache, oder im allgemeinen innerhalb eines funktionalen Programmierparadigmas.

Weitere Informationen über „Datenfluß Computing“, die Suche nach diesen beiden Worten auf Wikipedia oder mit Ihrer bevorzugten Suchmaschine. Die allgemeine Idee ist folgende: das Programm eine grafische Darstellung der Knoten gerichtet ist, die jeweils eine einfache Berechnung durchführen. Diese Knoten sind miteinander verbunden durch den Graphen Links, die die Ausgaben einiger Knoten an die Eingänge der anderen zur Verfügung stellen.

, wenn ein Knoten oder Bränden führt die Berechnung, die angeschlossenen Knoten zu seinen Ausgängen ihre entsprechenden Eingänge haben „ausgelöst“ oder „markiert“. Jeder Knoten, der alle Eingänge ausgelöst / markiert / verfügbar automatisch ausgelöst. Die Grafik kann implizit oder explizit sein, je nachdem, wie genau reaktive Programmierung implementiert ist.

Die Knoten können parallel betrachtet werden bei wie Brennen, aber oft sind sie seriell oder mit begrenzten Parallelität ausgeführt (zum Beispiel kann es ein paar Fäden sein, sie ausgeführt wird). Ein berühmtes Beispiel war der Manchester Datenfluß-Maschine , die (IIRC) ein markiertes Datenarchitektur verwendet Zeitplan Ausführung der Knoten in dem Graphen durch eine oder mehr Ausführungseinheiten. Dataflow-Computing ist ziemlich gut geeignet, um Situationen, in denen auslösenden Berechnungen asynchron Anstieg zu Kaskaden von Berechnungen geben funktionieren besser als zu versuchen, die Ausführung haben durch eine Uhr geregelt (oder Uhren).

Reactive Programmierung importiert diese „Kaskade der Ausführung“ Idee und scheint in einem Datenfluß artig des Programms zu denken, aber mit der Maßgabe, dass einige der Knoten auf der „Außenwelt“ angeschlossen sind und die Kaskaden der Ausführung ausgelöst werden wenn diese Sinnesartigen Knoten ändern. Die Programmausführung würde dann folgendermaßen aussehen etwas analog zu einem komplexen Reflexbogen. Das Programm kann oder nicht grundsätzlich sessile zwischen Stimuli oder in einen grundsätzlich sessilen Zustand zwischen Stimuli absetzen kann.

„nicht-reaktiv“ Programmierung mit einem ganz anderen Blick auf den Ablauf der Ausführung und die Beziehung zu externen Eingängen programmieren würde. Es ist wahrscheinlich etwas subjektiv sein, da die Menschen wahrscheinlich versucht werden, etwas zu sagen, die sie auf externe Eingänge „reagiert“ reagiert. Aber ein Blick auf den Geist der Sache, ein Programm, das Umfragen eine Ereigniswarteschlange in einem festen Intervall und löst alle Ereignisse an Funktionen gefunden (oder Threads) weniger reaktiv ist (weil es nur auf eine Benutzereingabe bedient in einem festen Intervall). Wieder ist es der Geist der Sache hier:. Ein auf ein sehr niedriges Niveau und Programm in einer reaktiven Art und Weise auf ihn eine Abfrage Implementierung setzt mit einem schnellen Abfrageintervall in ein System vorstellen kann

Nach vielen Seiten über FRP Lesen kam ich endlich über this über FRP erleuchtenden schreiben, hat mich endlich verstehen, was FRP wirklich geht.

Ich zitiere unter Heinrich Apfelmus (Autor von reaktiver Banane).

  

Was ist das Wesen der funktionellen reaktiven Programmierung?

     

Eine gemeinsame Antwort wäre, dass „FRP ist alles über ein System beschreibt, in   zeitlich veränderliche Funktionen anstelle von wandelbaren Zustand“, und dass   wäre sicherlich nicht falsch sein. Dies ist die semantische Sicht. Aber in   meiner Meinung nach die tiefere, befriedigende Antwort wird durch die gegebene   Folgendes rein syntaktisches Kriterium:

     

Das Wesen der funktionellen reaktiver Programmierung ist das dynamische Verhalten eines Wertes vollständig zum Zeitpunkt der Erklärung angeben.

     

Nehmen Sie zum Beispiel das Beispiel eines Zählers: Sie haben zwei Tasten   mit „Up“ und „Down“, die verwendet werden können, um zu erhöhen oder verringern   der Zähler. Imperativ, würden Sie zuerst einen Anfangswert angeben   und dann ändern, wenn eine Taste gedrückt wird; so etwas wie folgt aus:

counter := 0                               -- initial value
on buttonUp   = (counter := counter + 1)   -- change it later
on buttonDown = (counter := counter - 1)
     

Der Punkt ist, dass zum Zeitpunkt der Erklärung, nur der Anfangswert   für den Zähler angegeben wird; das dynamische Verhalten des Zählers   implizit in dem Rest des Programmtextes. Im Gegensatz dazu funktionellen   reaktive Programmierung gibt das gesamte dynamische Verhalten zu der Zeit   der Erklärung, wie folgt aus:

counter :: Behavior Int
counter = accumulate ($) 0
            (fmap (+1) eventUp
             `union` fmap (subtract 1) eventDown)
     

Wenn Sie die Dynamik des Zählers verstehen wollen, müssen Sie nur   bei seiner Definition zu suchen. Alles, was ihm passieren kann, wird   erscheinen auf der rechten Seite. Das ist sehr viel im Gegensatz zu dem   Imperativ Ansatz, bei der nachfolgenden Erklärungen des ändern   dynamisches Verhalten der zuvor angegebene Werte.

Also, in mein Verständnis ein FRP-Programm ist ein Satz von Gleichungen: eingeben Bild Beschreibung hier

j ist diskret: 1,2,3,4 ...

f hängt von t so beinhaltet dies die possiblilty äußere Reize zu modellieren

alle Zustand des Programms wird in Variablen verkapselt x_i

Die FRP Bibliothek kümmert Zeit voran, mit anderen Worten, unter j j+1.

Ich erkläre diese Gleichungen in viel mehr Details in dieses Video .

EDIT:

Etwa 2 Jahre nach der ursprünglichen Antwort, vor kurzem kam ich zu dem Schluss, dass FRP-Implementierungen eines weiteren wichtigen Aspekt haben. Sie müssen (und in der Regel tun) lösen ein wichtiges praktisches Problem. Cache-Annullierungs

Die Gleichungen für x_i-s einen Abhängigkeitsgraphen beschreiben. Wenn einige der x_i Änderungen zum Zeitpunkt j dann aktualisiert werden nicht alle anderen x_i' Werte bei j+1 müssen, die alle so nicht die Notwendigkeit, Abhängigkeiten neu berechnet werden, weil einige x_i' von x_i unabhängig sein könnten.

Darüber hinaus x_i-s, die Änderung tut inkrementell aktualisiert werden kann. Zum Beispiel lassen Sie sich eine Karte Operation f=g.map(_+1) in Scala betrachten, wo f und g aus List Ints. Hier f entspricht x_i(t_j) und g ist x_j(t_j). Nun, wenn ich ein Element prepend g dann wäre es ineffizient, die map Betrieb für alle Elemente in g auszuführen. Einige FRP-Implementierungen (zB reflex frp ) zielen darauf ab, dieses Problem zu lösen. Dieses Problem kann auch als inkrementeller Computing.

Mit anderen Worten, Verhalten (die x_i-s) in FRP kann als Cache-ed Berechnungen gedacht werden. Es ist die Aufgabe des FRP-Motor diese Cache-s (die x_i-s), wenn einige der f_i-s ändern sich effizient zu entkräften und neu zu berechnen.

Das Papier Einfach effizient funktionelle Reaktivität von Conal Elliott ( direkter PDF , 233 KB) ist eine ziemlich gute Einführung . Die entsprechende Bibliothek funktioniert auch.

Das Papier nun von einem anderen Papier abgelöst wird, Push-Pull-funktionelle reaktive Programmierung ( direkten PDF , 286 KB).

Disclaimer: Meine Antwort ist im Zusammenhang mit der rx.js - eine ‚reaktive Programmierung‘ Bibliothek für JavaScript

.

In der funktionalen Programmierung, statt einer Sammlung durch jedes Element iteriert, wenden Sie Funktionen höherer Ordnung (Hofs) der Sammlung selbst. So ist die Idee hinter FRP ist, dass statt jedes einzelnes Ereignis zu verarbeiten, um einen Strom von Ereignissen erstellen (umgesetzt mit einer beobachtbaren *) und gilt Hofs zu diesem statt. Auf diese Weise können Sie das System als Datenleitungen verbinden Verlage an die Abonnenten visualisieren.

Die wichtigsten Vorteile der Verwendung eines beobachtbar sind:
i) abstrahiert Zustand aus dem Code entfernt, zum Beispiel, wenn Sie die Event-Handler nur gefeuert werden wollen für jeden ‚n-te Ereignis oder stoppen nach den ersten Brennen‚n‘Ereignissen oder beginnen erst nach dem ersten Brennen‘ n "Ereignisse, kann man einfach die Höfs verwenden (Filter, takeUntil, überspringen respectively) statt Einstellung, die Aktualisierung und Überprüfung Zähler.
ii) es verbessert Code Ort - wenn Sie 5 verschiedene Event-Handler haben den Status einer Komponente ändern, können Sie ihre Observablen fusionieren und einen einzigen Event-Handler auf die fusionierte beobachtbaren stattdessen definieren, effektiv die Kombination von 5 Event-Handler in 1. Dies macht es sehr leicht, über welche Ereignisse in Ihrem gesamten System auf Grund eine Komponente beeinflussen kann, da sie alle in einem einzigen Handler sind.

  • beobachtbares ist die duale ein Iterable.

Ein Iterable ist eine träge verbraucht Sequenz - jedes Element wird durch den Iterator gezogen, wann immer er will, es zu benutzen, und daher wird die Auszählung durch den Verbraucher angetrieben.

Eine beobachtbar ist eine träge erzeugt Sequenz - jedes Element wird den Beobachter geschoben, wenn sie in die Sequenz hinzugefügt wird, und daher wird die Auszählung durch den Hersteller angetrieben.

Dude, das ist eine verdammt brillante Idee! Warum habe ich im Jahr 1998 über diese zurück nicht herausfinden? Wie auch immer, hier ist meine Interpretation der Fran Tutorial. Vorschläge sind herzlich willkommen, ich denke an ein Game-Engine auf dieser Basis zu starten.

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()

Kurz gesagt: Wenn jede Komponente wie eine Nummer behandelt wird, kann das gesamte System wie eine mathematische Gleichung behandelt wird, nicht wahr

Paul Hudak Buch The Haskell School of Expression , ist nicht nur eine gute Einführung in Haskell, aber es verbringt auch eine Menge Zeit auf FRP. Wenn Sie ein Anfänger mit FRP sind, empfehle ich es, um Ihnen ein Gefühl dafür, wie FRP funktioniert.

Es ist auch das, was wie eine neue Umschreiben dieses Buchs sieht (2011 veröffentlicht, aktualisiert 2014), Die Haskell School of Music .

Nach den bisherigen Antworten, scheint es, dass mathematisch wir einfach in einer höheren Ordnung denken. Stattdessen Wert des Denkens x mit Typ X , denken wir an eine Funktion x : T X , wobei T die Art der Zeit ist es, die natürlichen Zahlen, die ganzen Zahlen oder das Kontinuum. Nun, wenn wir schreiben y : = x + 1 in der Programmiersprache, meinen wir eigentlich die Gleichung y ( t ) = x ( t ) + 1.

Wirkt wie ein Tabellenkalkulationsprogramm wie angegeben. In der Regel auf der Basis eines ereignisgesteuerten Rahmen.

Wie bei allen „Paradigmen“, es ist Neuheit, ist fraglich.

Aus meiner Erfahrung von verteilten Stromnetzen von Akteuren, kann es leicht zum Opfer zu einem allgemeinen Problem der staatlichen Konsistenz über das Netzwerk von Knoten fällt das heißt Sie mit vieler Schwingung am Ende und Trapping in seltsamen Schleifen.

Das ist schwer zu vermeiden, da einige Semantik Referenz Schleifen oder Rundfunk bedeuten, und kann als Netzwerk von Akteuren konvergent (oder nicht) auf einigen unberechenbaren Zustand ziemlich chaotisch sein.

In ähnlicher Weise können einige Staaten nicht erreicht werden, obwohl sie gut definierten Kanten, weil der globale Zustand aus der Lösung entfernt lenkt. 2 + 2 kann oder auch nicht bekommen 4 sein je nachdem, wann die 2 Jahre wurden 2, und ob sie blieben auf diese Weise. Tabellen haben synchrone Takte und die Schleifenerfassung. Verteilen Akteure tun im Allgemeinen nicht.

Alle Spaß:)

.

Ich fand dieses schöne Video auf dem Clojure subreddit über FRP. Es ist ziemlich einfach, auch zu verstehen, wenn Sie Clojure nicht kennen.

Hier ist das Video: http://www.youtube.com/watch?v=nket0K1RXU4

Hier ist die Quelle des Video in der 2. Hälfte bezieht sich: https://github.com/Cicayda/yolk-examples/blob/master/src/yolk_examples/client/autocomplete.cljs

diesem Artikel von Andre Staltz ist die beste und klarste Erklärung, die ich bisher gesehen habe.

Einige Zitate aus dem Artikel:

  

Reactive Programmierung Programmierung mit asynchronen Datenströmen.

     

Hinzu kommt, dass Sie eine erstaunliche Toolbox von Funktionen gegeben zu kombinieren, zu schaffen und jede dieser Ströme zu filtern.

Hier ist ein Beispiel der fantastischen Diagramme, die ein Teil des Artikels sind:

 Ereignisstrom-Diagramm

Klicken Sie

Es ist über mathematische Daten-Transformationen im Laufe der Zeit (oder die Zeit ignorieren).

Im code bedeutet dies, funktionale Reinheit und die deklarative Programmierung.

Zustand bugs sind ein großes problem in der standard-imperativen Paradigma.Verschiedene bits von code ändern kann einen freigegebenen Zustand zu verschiedenen "Zeiten" in die Programme der Ausführung.Dies ist schwer zu behandeln.

In den FRP Sie beschreiben (wie im deklarativen Programmierung), wie Daten transformiert sich von einem Zustand in einen anderen, und was es auslöst.Dies ermöglicht Sie zu ignorieren die Zeit, da Sie Ihre Funktion ist einfach zu reagieren Ihre Eingaben und Ihre aktuellen Werte, um eine neue zu erstellen.Dies bedeutet, dass der Staat die in den Graphen (oder Baum) der transformation Knoten und ist rein funktional.

Dies Massiv die Komplexität verringert und die debugging-Zeit.

Denken Sie an den Unterschied zwischen " A=B+C in der Mathematik und in A=B+C in einem Programm.In der Mathematik haben Sie eine Beziehung beschreibt, dass wird sich nie ändern.In einem Programm, der sagt, dass "jetzt" Eine ist B+C.Aber der nächste Befehl sein könnte, B++, in dem Fall A ist nicht gleich B+C.In Mathe oder deklarative Programmierung wird immer gleich B+C egal was Punkt in der Zeit, die Sie Fragen,.

Also durch die Beseitigung der Komplexität von shared-state und ändern von Werten über die Zeit.Ihr Programm ist viel einfacher zu Grunde geht.

Ein EventStream ist ein EventStream + einige transformation Funktion.

Ein Verhalten ist ein EventStream + Einige Wert im Speicher.

Wenn das Ereignis ausgelöst wird der Wert aktualisiert wird, durch ausführen der transformation Funktion.Der Wert, den dieses liefert, ist gespeichert in die Verhaltensweisen Speicher.

Verhaltensweisen, die kombiniert werden können, die zur Herstellung neuer Verhaltensweisen, die eine transformation auf N anderen Verhaltensweisen.Dieses komponierte Wert neu berechnet, wie die input-Ereignisse (Verhalten) Feuer.

"Da Beobachter sind staatenlos, müssen wir oft mehrere von Ihnen, um zu simulieren eine state-Maschine wie in der drag-Beispiel.Wir haben zum speichern des Status, wo der Zugriff für alle beteiligten Beobachter wie in der path-variable vor."

Zitat aus Selbstironisch Das Observer-Muster http://infoscience.epfl.ch/record/148043/files/DeprecatingObserversTR2010.pdf

Die kurze und klare Erklärung über Reactive Programmierung erscheint auf Cyclejs - Reactive Programming , verwendet es einfache und visuelle Muster.

  

A [Modul / Component / object] reaktiv ist bedeutet es voll verantwortlich ist   für durch die Reaktion auf externe Ereignisse ihren eigenen Zustand zu verwalten.

     

Was ist der Vorteil dieses Ansatzes? Es ist Inversion of Control ,   vor allem, weil [Modul / Component / object] ist für mich selbst verantwortlich, die Verbesserung der Verkapselung private Methoden gegen die öffentlich denjenigen verwendet wird.

Es ist ein guter Startpunkt, nicht eine vollständige Quelle des Wissens. Von dort aus konnte man zu komplexeren und tiefen Papieren springen.

Überprüfen Sie heraus Rx, Reactive Extensions für .NET. Sie weisen darauf hin, dass mit IEnumerable Sie sind grundsätzlich ‚ziehen‘ aus einem Stream. Linq Abfragen über IQueryable / IEnumerable sind Operationen festgelegt, dass ‚saugen‘ die Ergebnisse aus einem Satz. Aber mit den gleichen Betreiber über IObservable können Sie Linq-Abfragen schreiben, die ‚reagieren‘.

Zum Beispiel könnten Sie eine Linq-Abfrage schreiben wie (Von m in MyObservableSetOfMouseMovements wo m.X <100 und m.Y <100 wählen new Point (m.X, m.Y)).

und mit den Rx-Erweiterungen, das ist es: Sie haben UI-Code, der von Mausbewegungen auf den eingehenden Strom reagiert und zieht, wenn Sie in der 100.100-Box sind ...

FRP ist eine Kombination aus funktionaler Programmierung (Programmierparadigma auf der Idee, alles eingebaut ist eine Funktion) und Blindprogrammierparadigma (auf der Idee, dass alles ist ein Strom (Beobachter und beobachtbaren Philosophie)). Es wird angenommen, das Beste aus den Welten sein.

Schauen Sie sich Andre Staltz Post auf reaktive Programmierung mit zu beginnen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top