IMHO ist das Binden einer Variablen an eine andere Variable oder einen Ausdruck ein sehr verbreitetes Szenario in der Mathematik. Tatsächlich denken viele Schüler am Anfang, dass der Zuweisungsoperator (=) eine Art Bindung ist. In den meisten Sprachen wird die Bindung jedoch nicht als native Funktion unterstützt. In einigen Sprachen wie C # wird die Bindung in einigen Fällen unter bestimmten Bedingungen unterstützt.
IMHO war die Implementierung dieser Funktion als native Funktion jedoch so einfach wie das Ändern des folgenden Codes:
int a,b,sum;
sum := a + b;
a = 10;
b = 20;
a++;
zu diesem-
int a,b,sum;
a = 10;
sum = a + b;
b = 20;
sum = a + b;
a++;
sum = a + b;
Dies bedeutet, dass die Bindungsanweisung nach jeder Anweisung als Zuweisung platziert wird, wobei die Werte einer der im Ausdruck enthaltenen Variablen auf der rechten Seite geändert werden. Danach können redundante Anweisungen (oder die Optimierung in der Assembly nach der Kompilierung) gekürzt werden.
Warum wird es in den meisten Sprachen nicht nativ unterstützt? Speziell in der C-Sprachfamilie?
Aktualisieren:
Aus unterschiedlichen Meinungen denke ich, ich sollte diese vorgeschlagene "Bindung" genauer definieren.
- Dies ist eine Einbahnstraße. Nur die Summe ist an a + b gebunden, nicht umgekehrt.
- Der Umfang der Bindung ist lokal.
- Sobald die Bindung hergestellt ist, kann sie nicht mehr geändert werden. Das heißt, sobald die Summe an a + b gebunden ist, ist die Summe immer a + b.
Hoffe, die Idee ist jetzt klarer.
Update 2:
Ich wollte nur diese P # -Funktion . Hoffe, dass es in Zukunft dort sein wird.
quelle
Antworten:
Sie verwechseln Programmieren mit Mathematik. Nicht einmal funktionale Programmierung ist rein mathematisch, obwohl sie viele Ideen entlehnt und sie in etwas verwandelt, das ausgeführt und für die Programmierung verwendet werden kann. Imperative Programmierung (die die meisten C-inspirierten Sprachen umfasst, mit Ausnahme von JavaScript und den neueren Ergänzungen zu C #) hat fast nichts mit Mathematik zu tun. Warum sollten sich diese Variablen also wie Variablen in Mathematik verhalten?
Sie müssen berücksichtigen, dass dies nicht immer das ist, was Sie wollen. So viele Menschen werden von Verschlüssen gebissen, die speziell in Schleifen erstellt wurden, weil Verschlüsse die Variable behalten und nicht irgendwann eine Kopie ihres Werts, dh
for (i = 0; i < 10; i++) { var f = function() { return i; }; /* store f */ }
zehn Verschlüsse erstellen, die zurückkehren9
. Sie müssten also beide Möglichkeiten unterstützen - was die doppelten Kosten für das "Komplexitätsbudget" und einen weiteren Betreiber bedeutet. Möglicherweise auch Inkompatibilitäten zwischen Code, der dies verwendet, und Code, der dies nicht verwendet, es sei denn, das Typsystem ist ausgefeilt genug (mehr Komplexität!).Auch eine effiziente Implementierung ist sehr schwierig. Die naive Implementierung fügt jeder Aufgabe einen konstanten Overhead hinzu , der sich in imperativen Programmen schnell summieren kann. Andere Implementierungen können Aktualisierungen verzögern, bis die Variable gelesen wird. Dies ist jedoch erheblich komplexer und hat auch dann noch Overhead, wenn die Variable nie wieder gelesen wird. Ein ausreichend intelligenter Compiler kann beide optimieren, aber ausreichend intelligente Compiler sind selten und erfordern viel Aufwand beim Erstellen (beachten Sie, dass dies nicht immer so einfach ist wie in Ihrem Beispiel, insbesondere wenn die Variablen einen breiten Anwendungsbereich haben und Multithreading ins Spiel kommt!).
Beachten Sie, dass es bei der reaktiven Programmierung im Wesentlichen darum geht (soweit ich das beurteilen kann), also existiert sie. In traditionellen Programmiersprachen ist das einfach nicht so üblich. Und ich wette, einige der Implementierungsprobleme, die ich im vorherigen Absatz aufgeführt habe, sind gelöst.
quelle
Es passt sehr schlecht zu den meisten Programmiermodellen. Es würde eine Art völlig unkontrollierte Fernwirkung darstellen, bei der man den Wert von Hunderten oder Tausenden von Variablen und Objektfeldern durch eine einzige Zuweisung zerstören könnte.
quelle
a
oder schreibenb
, müssen Sie die Auswirkungen auf jeden einzelnen verwendeten Ortsum
und jeden Ort, den Sie lesensum
, berücksichtigen. Sie müssen überlegen, wasa
und was Sieb
tun. In nicht trivialen Fällen kann dies kompliziert werden, insbesondere wenn sich der tatsächlich gebundene Ausdruck zursum
Laufzeit ändern kann.Weißt du, ich habe das nervige Gefühl, dass reaktive Programmierung in einer Web2.0-Umgebung cool sein könnte. Warum das Gefühl? Nun, ich habe diese eine Seite, die meistens eine Tabelle ist, die sich als Reaktion auf onClick-Ereignisse in Tabellenzellen ständig ändert. Und Zellklicks bedeuten oft, die Klasse aller Zellen in einer Spalte oder Zeile zu ändern. und das bedeutet endlose Schleifen von getRefToDiv () und dergleichen, um andere verwandte Zellen zu finden.
IOW, viele der ~ 3000 Zeilen JavaScript, die ich geschrieben habe, tun nichts anderes, als Objekte zu lokalisieren. Vielleicht könnte reaktive Programmierung all das zu geringen Kosten tun; und bei einer enormen Reduzierung der Codezeilen.
Was haltet ihr davon? Ja, ich stelle fest, dass meine Tabelle viele Tabellenkalkulationsfunktionen enthält.
quelle
Ich denke, was Sie beschreiben, wird als Tabellenkalkulation bezeichnet:
... dann Bewertung der
B1
Renditen 7.BEARBEITEN
Die C-Sprache wird manchmal als "tragbare Baugruppe" bezeichnet. Es ist eine zwingende Sprache, während Tabellenkalkulationen usw. deklarative Sprachen sind. Das Sagen
B1=A1+1
und ErwartenB1
einer Neubewertung bei ÄnderungenA1
ist definitiv deklarativ. Deklarative Sprachen (von denen funktionale Sprachen eine Teilmenge sind) werden im Allgemeinen als übergeordnete Sprachen betrachtet, da sie weiter von der Funktionsweise der Hardware entfernt sind.In einem ähnlichen Zusammenhang sind Automatisierungssprachen wie die Kontaktplanlogik normalerweise deklarativ. Wenn Sie eine Sprosse der Logik schreiben , die sagen ,
output A = input B OR input C
es wird neu zu bewerten diese Aussage immer wieder undA
kann , wann immer ändernB
oderC
Änderungen. Andere Automatisierungssprachen wie das Funktionsblockdiagramm (mit dem Sie möglicherweise vertraut sind, wenn Sie Simulink verwendet haben) sind ebenfalls deklarativ und werden kontinuierlich ausgeführt.Einige (eingebettete) Automatisierungsgeräte sind in C programmiert, und wenn es sich um ein Echtzeitsystem handelt, verfügt es wahrscheinlich über eine Endlosschleife, die die Logik immer wieder neu ausführt, ähnlich wie die Kontaktplanlogik ausgeführt wird. In diesem Fall könnten Sie in Ihre Hauptschleife schreiben:
... und da es ständig ausgeführt wird, wird es deklarativ.
A
wird ständig neu bewertet.quelle
C, C ++, Ziel-C:
Blöcke bieten die Bindungsfunktion, nach der Sie suchen.
In Ihrem Beispiel:
Sie setzen
sum
auf den Ausdrucka + b
in einem Kontext, in dema
undb
Variablen vorhanden sind. Sie können genau das mit einem "Block" (alias Closure, alias Lambda-Ausdruck) in C, C ++ oder Objective-C mit Apples Erweiterungen (pdf) tun :Dies setzt
sum
auf einen Block, der die Summe von a und b zurückgibt. Der__block
Speicherklassenspezifizierer gibt dies ana
undb
kann sich ändern. In Anbetracht dessen können wir den folgenden Code ausführen:und erhalten Sie die Ausgabe:
Der einzige Unterschied zwischen der Verwendung eines Blocks und der von Ihnen vorgeschlagenen "Bindung" besteht in dem leeren Klammerpaar in
sum()
. Der Unterschied zwischensum
undsum()
ist der Unterschied zwischen einem Ausdruck und dem Ergebnis dieses Ausdrucks. Beachten Sie, dass wie bei Funktionen die Klammern nicht leer sein müssen - Blöcke können ebenso wie Funktionen Parameter annehmen.quelle
C ++
Aktualisiert, um generisch zu sein. Parametriert bei Rückgabe- und Eingabetypen. Kann jede binäre Operation liefern, die die parametrisierten Typen erfüllt. Code berechnet das Ergebnis auf Anfrage. Es versucht, die Ergebnisse nicht neu zu berechnen, wenn es damit durchkommt. Nehmen Sie dies heraus, wenn dies unerwünscht ist (aufgrund von Nebenwirkungen, weil die enthaltenen Objekte groß sind, aus irgendeinem Grund).
quelle