IMHO powiązanie zmiennej z inną zmienną lub wyrażeniem jest bardzo częstym scenariuszem w matematyce. W rzeczywistości na początku wielu uczniów uważa, że operator przypisania (=) jest rodzajem wiązania. Ale w większości języków wiązanie nie jest obsługiwane jako funkcja natywna. W niektórych językach, takich jak C #, wiązanie jest obsługiwane w niektórych przypadkach, przy spełnieniu niektórych warunków.
Ale IMHO zaimplementowanie tego jako funkcji natywnej było tak proste, jak zmiana następującego kodu:
int a,b,sum;
sum := a + b;
a = 10;
b = 20;
a++;
do tego-
int a,b,sum;
a = 10;
sum = a + b;
b = 20;
sum = a + b;
a++;
sum = a + b;
Oznacza umieszczenie instrukcji wiązania jako przypisań po każdej instrukcji zmieniającej wartości dowolnej zmiennej zawartej w wyrażeniu po prawej stronie. Po tym nastąpi przycięcie zbędnych instrukcji (lub optymalizacja w zestawie po kompilacji).
Dlaczego więc nie jest obsługiwany natywnie w większości języków. Szczególnie w rodzinie języków C?
Aktualizacja:
Z różnych opinii uważam, że powinienem bardziej precyzyjnie zdefiniować proponowane „wiążące”
- Jest to wiążące w jedną stronę. Tylko suma jest związana z + +, a nie odwrotnie.
- Zakres powiązania jest lokalny.
- Po ustanowieniu powiązania nie można go zmienić. Oznacza to, że gdy suma zostanie przypisana do + b, suma zawsze będzie a + b.
Mam nadzieję, że pomysł jest teraz jaśniejszy.
Aktualizacja 2:
Chciałem tylko tej funkcji P # . Mam nadzieję, że będzie tam w przyszłości.
źródło
Odpowiedzi:
Mylisz programowanie z matematyką. Nawet funkcjonalne programowanie nie jest całkowicie matematyczne, chociaż zapożycza wiele pomysłów i zamienia je w coś, co można wykonać i wykorzystać do programowania. Programowanie imperatywne (które obejmuje większość języków inspirowanych językiem C, godne uwagi wyjątki to JavaScript i nowsze dodatki do C #) nie ma prawie nic wspólnego z matematyką, więc dlaczego te zmienne powinny zachowywać się jak zmienne matematyczne?
Musisz wziąć pod uwagę, że nie zawsze jest to, czego chcesz. Tak wiele osób jest gryzionych przez zamknięcia utworzone w pętlach, ponieważ zamknięcia zachowują zmienną, a nie kopię jej wartości w pewnym momencie, tj.
for (i = 0; i < 10; i++) { var f = function() { return i; }; /* store f */ }
Tworzy dziesięć zamknięć, które powracają9
. Trzeba więc wspierać w obie strony - co oznacza dwukrotność kosztu „budżetu złożoności” i jeszcze jednego operatora. Być może także niezgodności między kodem używającym tego a kodem nieużywającym tego, chyba że system typów jest wystarczająco zaawansowany (większa złożoność!).Również skuteczne wdrożenie tego jest bardzo trudne. Naiwna implementacja powoduje stałe obciążenie każdego zadania, które może szybko zsumować się w programach imperatywnych. Inne implementacje mogą opóźniać aktualizacje, dopóki zmienna nie zostanie odczytana, ale jest to znacznie bardziej złożone i wciąż ma narzut, nawet jeśli zmienna nigdy nie zostanie odczytana ponownie. Wystarczająco inteligentny kompilator może zoptymalizować oba, ale wystarczająco inteligentne kompilatory są rzadkie i wymagają dużego wysiłku, aby je utworzyć (pamiętaj, że nie zawsze jest to tak proste jak w twoim przykładzie, szczególnie gdy zmienne mają szeroki zakres i wielowątkowość wchodzi w grę!).
Zauważ, że programowanie reaktywne jest w zasadzie o tym (o ile mogę powiedzieć), więc istnieje. To po prostu nie jest tak powszechne w tradycyjnych językach programowania. Założę się, że niektóre problemy z implementacjami wymienione w poprzednim akapicie zostały rozwiązane.
źródło
Bardzo słabo pasuje do większości modeli programowania. Byłby to rodzaj całkowicie niekontrolowanej akcji na odległość, w której można zniszczyć wartość setek lub tysięcy zmiennych i pól obiektowych, wykonując jedno przypisanie.
źródło
a
lubb
, musisz rozważyć jego wpływ na każdesum
używane miejsce i każde miejsce, które czytaszsum
, musisz zastanowić się, coa
ib
robisz. W przypadkach innych niż trywialne może się to skomplikować, szczególnie jeśli rzeczywiste wyrażenie, do którego się odnosi,sum
może się zmienić w czasie wykonywania.Wiem, mam dokuczliwe przeczucie, że reaktywne programowanie może być fajne w środowisku Web2.0. Skąd to uczucie? Cóż, mam tę jedną stronę, która jest głównie tabelą, która zmienia się cały czas w odpowiedzi na zdarzenia onClick w komórkach tabeli. Kliknięcia komórek często oznaczają zmianę klasy wszystkich komórek w kolumnie lub wierszu; a to oznacza niekończące się pętle getRefToDiv () i tym podobnych, aby znaleźć inne powiązane komórki.
IOW, wiele z ~ 3000 wierszy JavaScript, które napisałem, nic nie robi, tylko lokalizuje obiekty. Może programowanie reaktywne może to wszystko zrobić przy niewielkich kosztach; i przy ogromnej redukcji linii kodu.
Co o tym myślicie? Tak, zauważam, że mój stół ma wiele funkcji podobnych do arkusza kalkulacyjnego.
źródło
Myślę, że to, co opisujesz, nazywa się arkusz kalkulacyjny:
... następnie oceniając
B1
zwroty 7.EDYTOWAĆ
Język C jest czasem nazywany „przenośnym zestawem”. Jest to język imperatywny, podczas gdy arkusze kalkulacyjne itp. Są językami deklaratywnymi. Mówienie
B1=A1+1
i oczekiwanieB1
ponownej oceny po zmianieA1
jest zdecydowanie deklaratywne. Języki deklaratywne (których podzbiórami są języki funkcjonalne) są ogólnie uważane za języki wyższego poziomu, ponieważ są bardziej oddalone od sposobu działania sprzętu.W pokrewnej uwadze języki automatyzacji, takie jak logika drabinkowa, są zazwyczaj deklaratywne. Jeśli napiszesz szczebel logiki, który mówi,
output A = input B OR input C
że będzie stale oceniać to stwierdzenie iA
może się zmieniać za każdym razemB
lubC
zmieniać. Inne języki automatyzacji, takie jak schemat bloków funkcyjnych (który możesz znać, jeśli korzystałeś z Simulink), są również deklaratywne i działają w sposób ciągły.Niektóre (wbudowane) urządzenia automatyzacyjne są zaprogramowane w C, a jeśli jest to system czasu rzeczywistego, prawdopodobnie ma nieskończoną pętlę, która ponownie wykonuje logikę w kółko, podobnie jak logika drabinkowa. W takim przypadku w głównej pętli możesz napisać:
... a ponieważ cały czas działa, staje się deklaratywny.
A
będzie stale poddawany ponownej ocenie.źródło
C, C ++, Objective-C:
Bloki zapewniają funkcję wiązania, której szukasz.
W twoim przykładzie:
jesteś ustawienie
sum
do wyrażeniaa + b
w kontekście, w któryma
ib
są istniejące zmienne. Możesz to zrobić za pomocą „bloku” (aka closure, aka lambda expression) w C, C ++ lub Objective-C z rozszerzeniami Apple (pdf):Ustawia
sum
się na blok, który zwraca sumę aib. Specyfikator__block
klasy pamięci wskazuje toa
ib
może się zmienić. Biorąc powyższe pod uwagę, możemy uruchomić następujący kod:i uzyskaj wynik:
Jedyną różnicą między użyciem bloku a proponowanym „wiązaniem” jest pusta para nawiasów w
sum()
. Różnica pomiędzysum
asum()
stanowi różnicę między ekspresji i wyniku tej ekspresji. Zauważ, że podobnie jak w przypadku funkcji, nawiasy nie muszą być puste - bloki mogą przyjmować parametry tak jak funkcje.źródło
C ++
Zaktualizowano, aby był ogólny. Sparametryzowane na typach zwrotów i wejściowych. Może dostarczyć dowolną operację binarną spełniającą sparametryzowane typy. Kod oblicza wynik na żądanie. Stara się nie przeliczać wyników, jeśli da sobie radę. Wyjmij to, jeśli jest to niepożądane (z powodu skutków ubocznych, ponieważ zawarte obiekty są duże, z jakiegokolwiek powodu).
źródło