Ciągle słyszę ten termin w różnych kontekstach. Co to jest?
Ciągle słyszę ten termin w różnych kontekstach. Co to jest?
Odpowiedzi:
Programowanie deklaratywne polega na pisaniu kodu w sposób opisujący to, co chcesz zrobić, a nie sposób, w jaki chcesz to zrobić. Kompilator musi ustalić, jak to zrobić.
Przykładami deklaratywnych języków programowania są SQL i Prolog.
Inne odpowiedzi już fantastycznie wyjaśniają, czym jest programowanie deklaratywne, dlatego przedstawię kilka przykładów, dlaczego może to być przydatne.
Programy deklaratywne są niezależne od kontekstu . Ponieważ deklarują jedynie ostateczny cel, ale nie pośrednie kroki do osiągnięcia tego celu, ten sam program może być wykorzystywany w różnych kontekstach. Jest to trudne w przypadku programów imperatywnych , ponieważ często zależą one od kontekstu (np. Stan ukryty).
Weź yacc
jako przykład. Jest to także generator parserów. kompilator kompilator, zewnętrzna deklaratywna DSL do opisywania gramatyki języka, dzięki czemu parser dla tego języka może być automatycznie generowany z opisu. Ze względu na niezależność od kontekstu, przy pomocy takiej gramatyki możesz robić wiele różnych rzeczy:
yacc
)I wiele więcej …
Ponieważ nie określasz komputera, jakie kroki należy podjąć i w jakiej kolejności, może on znacznie swobodniej zmieniać układ programu, a nawet wykonywać niektóre zadania równolegle. Dobrym przykładem jest planer zapytań i optymalizator zapytań do bazy danych SQL. Większość baz danych SQL pozwala wyświetlić zapytanie, które faktycznie wykonują, w porównaniu z zapytaniem, o które je poprosiłeś . Często te zapytania nic nie wyglądająlubią się nawzajem. Planer zapytań bierze pod uwagę rzeczy, o których nawet byś nie marzył: na przykład opóźnienie obrotu talerza dysku lub fakt, że jakaś inna aplikacja dla zupełnie innego użytkownika właśnie wykonała podobne zapytanie i tabelę, którą jesteś dołączanie się i że tak ciężko pracowałeś, aby uniknąć ładowania, i tak jest już w pamięci.
Jest to ciekawy kompromis tutaj: maszyna musi pracować ciężej, aby dowiedzieć się, jak coś zrobić, niż miałoby to miejsce w języku bezwzględnej, ale kiedy to robi zrozumieć to, że ma znacznie większą swobodę i wiele więcej informacji na optymalizację etap.
Luźno:
Programowanie deklaratywne dąży do:
Programowanie imperatywne dąży do:
W rezultacie styl imperatywny pomaga czytelnikowi zrozumieć mechanikę tego, co faktycznie robi system, ale może dać niewielki wgląd w problem, który ma rozwiązać. Z drugiej strony deklaratywny styl pomaga czytelnikowi zrozumieć dziedzinę problemu i podejście, jakie system przyjmuje do rozwiązania problemu, ale jest mniej pouczający w kwestii mechaniki.
Prawdziwe programy (nawet te napisane w językach, które faworyzują końce spektrum, takie jak ProLog lub C) zazwyczaj mają oba style obecne w różnym stopniu w różnych punktach, aby zaspokoić różne złożoności i potrzeby komunikacyjne utworu. Jeden styl nie jest lepszy od drugiego; służą po prostu innym celom i, podobnie jak w przypadku wielu rzeczy w życiu, umiar jest kluczowy.
Oto przykład.
W CSS (używanym do stylizowania stron HTML), jeśli chcesz, aby element obrazu miał 100 pikseli wysokości i 100 pikseli szerokości, po prostu „oświadczasz”, że to, co chcesz, w następujący sposób:
#myImageId {
height: 100px;
width: 100px;
}
Możesz uznać CSS za deklaratywny język „arkusza stylów”.
Silnik przeglądarki, który czyta i interpretuje ten CSS, może sprawić, że obraz będzie wyglądał tak wysoko i tak szeroko, jak chce. Różne silniki przeglądarki (np. Silnik IE, silnik Chrome) będą realizować to zadanie inaczej.
Ich unikalne implementacje NIE są oczywiście napisane w języku deklaratywnym, ale w proceduralnym, takim jak Assembly, C, C ++, Java, JavaScript lub Python. Ten kod to kilka kroków, które należy wykonać krok po kroku (i mogą obejmować wywołania funkcji). Może to robić interpolować wartości pikseli i renderować na ekranie.
Przykro mi, ale muszę się nie zgodzić z wieloma innymi odpowiedziami. Chciałbym zatrzymać to mętne niezrozumienie definicji programowania deklaratywnego.
Definicja
Przezroczystość referencyjna (RT) wyrażeń podrzędnych jest jedynym wymaganym atrybutem deklaratywnego wyrażenia programistycznego , ponieważ jest to jedyny atrybut, który nie jest współdzielony z programowaniem imperatywnym.
Inne cytowane atrybuty programowania deklaratywnego pochodzą z tej RT. Kliknij powyższy link, aby uzyskać szczegółowe wyjaśnienie.
Przykład arkusza kalkulacyjnego
Dwie odpowiedzi wspomniały o programowaniu arkuszy kalkulacyjnych. W przypadkach, gdy programowanie arkusza kalkulacyjnego (inaczej formuł) nie ma dostępu do zmiennego stanu globalnego , jest to programowanie deklaratywne. To dlatego, że komórki Zmienne wartości są monolityczne wejście i wyjście z main()
(cały program). Nowe wartości nie są zapisywane w komórkach po wykonaniu każdej formuły, dlatego nie można ich modyfikować przez cały czas życia programu deklaratywnego (wykonanie wszystkich formuł w arkuszu kalkulacyjnym). W związku z tym formuły postrzegają te zmienne komórki jako niezmienne. Funkcja RT ma dostęp do niezmiennego stanu globalnego (a także zmiennego stanu lokalnego ).
Zatem zdolność do mutowania wartości w komórkach, gdy program kończy się (jako wyjście main()
), nie powoduje, że można je modyfikować przechowywane wartości w kontekście reguł. Kluczowym rozróżnieniem jest to, że wartości komórek nie są aktualizowane po wykonaniu każdej formuły arkusza kalkulacyjnego, dlatego kolejność wykonywania formuł nie ma znaczenia. Wartości komórek są aktualizowane po wykonaniu wszystkich formuł deklaratywnych.
Programowanie deklaratywne to obraz, przy czym programowanie imperatywne to instrukcje do malowania tego obrazu.
Pisząc w sposób deklaratywny, piszesz „Mówisz, co to jest”, zamiast opisywać kroki, jakie powinien podjąć komputer, aby dostać się tam, gdzie chcesz.
Kiedy używasz XML do oznaczania danych, używasz deklaratywnego programowania, ponieważ mówisz: „To jest osoba, która ma urodziny, a tam jest adres”.
Kilka przykładów połączenia programowania deklaratywnego i imperatywnego w celu uzyskania większego efektu:
Windows Presentation Foundation używa deklaratywnej składni XML do opisania wyglądu interfejsu użytkownika oraz relacji (powiązań) między kontrolkami i bazowymi strukturami danych.
Strukturalne pliki konfiguracyjne używają deklaratywnej składni (tak proste, jak pary „klucz = wartość”), aby zidentyfikować, co oznacza ciąg lub wartość danych.
HTML zaznacza tekst znacznikami, które opisują rolę każdego fragmentu tekstu w stosunku do całego dokumentu.
Programowanie deklaratywne to programowanie z deklaracjami, tzn. Zdaniami deklaratywnymi. Zdania deklaratywne mają szereg właściwości, które odróżniają je od zdań rozkazujących. W szczególności deklaracjami są:
Istotną kwestią jest to, że są to wszystkie właściwości strukturalne i są prostopadłe do przedmiotu. W deklaratywnym nie chodzi o „Co vs. Jak” . Możemy zadeklarować (reprezentować i ograniczyć) „jak” równie łatwo, jak deklarujemy „co” . Deklaratywna jest struktura, a nie treść. Programowanie deklaratywne ma znaczący wpływ na to, w jaki sposób wyodrębniamy i refaktoryzujemy nasz kod oraz jak modulujemy go do podprogramów, ale nie tak bardzo w modelu domeny.
Często możemy zmienić z trybu rozkazującego na tryb deklaratywny, dodając kontekst. Np. „Skręć w lewo. (... poczekaj na to ...) Skręć w prawo.” na „Bob skręci w lewo na skrzyżowaniu Foo i Bar o 11:01. Bob skręci w prawo na skrzyżowaniu Bar i Baz o 11:06”. Zauważ, że w tym drugim przypadku zdania są idempotentne i przemienne, podczas gdy w pierwszym przypadku zmiana lub powtórzenie zdań poważnie zmieniłoby znaczenie programu.
Jeśli chodzi o monotonię , deklaracje mogą dodawać ograniczenia, które odejmują możliwości . Ale ograniczenia wciąż dodają informacje (a dokładniej, ograniczenia są informacją). Jeśli potrzebujemy deklaracji zmieniających się w czasie, typowe jest modelowanie tego z wyraźną semantyką czasową - np. Od „kula jest płaska” do „kula jest płaska w czasie T”. Jeśli mamy dwie sprzeczne deklaracje, mamy niespójny system deklaratywny, chociaż można to rozwiązać poprzez wprowadzenie miękkich ograniczeń (priorytetów, prawdopodobieństw itp.) Lub wykorzystanie logiki parakonsekwentnej.
wyobraź sobie stronę programu Excel. Z kolumnami wypełnionymi formułami do obliczenia zwrotu podatku.
Cała logika jest zadeklarowana w komórkach, kolejność obliczeń jest ustalana na podstawie samej formuły, a nie proceduralnie.
Na tym właśnie polega programowanie deklaratywne. Zadeklarujesz przestrzeń problemu i rozwiązanie, a nie przebieg programu.
Prolog jest jedynym deklaratywnym językiem, którego używam. Wymaga to innego sposobu myślenia, ale dobrze jest nauczyć się, jeśli tylko narażasz się na coś innego niż typowy język programowania proceduralnego.
Dopracowałem swoje rozumienie programowania deklaratywnego od grudnia 2011 r., Kiedy udzieliłem odpowiedzi na to pytanie. Oto moje obecne zrozumienie.
Długa wersja mojego zrozumienia (badania) została szczegółowo opisana pod tym linkiem , który należy przeczytać, aby uzyskać głębokie zrozumienie podsumowania, które przedstawię poniżej.
Programowanie imperatywne polega na zapisywaniu i odczytywaniu stanu zmiennego, a zatem kolejność i / lub powielanie instrukcji programu może zmienić zachowanie programu (semantykę) (a nawet spowodować błąd, tj. Niezamierzone zachowanie).
W najbardziej naiwnym i ekstremalnym sensie (który twierdziłem w mojej poprzedniej odpowiedzi) programowanie deklaratywne (DP) unika całego przechowywanego stanu zmiennego, dlatego uporządkowanie i / lub powielanie instrukcji programu NIE może zmienić zachowania (semantyki) programu .
Jednak taka ekstremalna definicja nie byłaby bardzo przydatna w prawdziwym świecie, ponieważ prawie każdy program wymaga zmagazynowanego stanu. Na przykład arkusz kalkulacyjny zgodny z tą definicją ekstremalnych DP, ponieważ cały kod programu jest prowadzony do końca z jednego statycznego kopii stanu wejścia, zanim zostaną zapisane nowe kraje. Następnie, jeśli jakikolwiek stan zostanie zmieniony, jest to powtarzane. Ale większość programów w świecie rzeczywistym nie może być ograniczona do takiego monolitycznego modelu zmian stanu.
Bardziej użyteczną definicją DP jest to, że kolejność i / lub powielanie instrukcji programowania nie zmienia żadnej nieprzejrzystej semantyki. Innymi słowy, nie występują ukryte losowe zmiany semantyki - wszelkie zmiany w kolejności instrukcji programu i / lub duplikacji powodują jedynie zamierzone i przejrzyste zmiany w zachowaniu programu.
Następnym krokiem byłoby omówienie, które modele programowania lub paradygmaty pomagają w DP, ale nie o to tutaj chodzi.
Functional programming
jest obecnie modnym słowem, które jest zasadniczo podzbiorem deklaratywnego programowania. LINQ w języku C # jest elementem programowania funkcjonalnego, gdy sam język jest z natury konieczny. Tak więc C # staje się rodzajem hybrydy opartej na tej definicji.
Jest to metoda programowania oparta na opisie tego, co należy zrobić lub być, a nie na tym , jak to powinno działać.
Innymi słowy, nie piszesz algorytmów wykonanych z wyrażeń, po prostu układasz, jak chcesz, aby rzeczy były. Dwa dobre przykłady to HTML i WPF.
Ten artykuł w Wikipedii stanowi dobry przegląd: http://en.wikipedia.org/wiki/Declarative_programming
Ponieważ napisałem moją wcześniejszą odpowiedź, sformułowałem nową definicję właściwości deklaratywnej, która jest cytowana poniżej. Zdefiniowałem także programowanie imperatywne jako podwójną właściwość.
Ta definicja jest lepsza od tej, którą podałem w poprzedniej odpowiedzi, ponieważ jest zwięzła i bardziej ogólna. Ale może być trudniej zrozumieć, ponieważ implikacje twierdzeń o niekompletności mających zastosowanie do programowania i życia w ogólności są trudne dla ludzi, aby otoczyli umysł.
Cytowany wyjaśnienie definicji omawia rolę czysto funkcjonalne sztuki programowania w języku programowania deklaratywnego.
Deklaratywny kontra imperatywny
Właściwość deklaratywna jest dziwna, tępa i trudna do uchwycenia w technicznie precyzyjnej definicji, która pozostaje ogólna i niejednoznaczna, ponieważ jest to naiwne przekonanie, że możemy zadeklarować znaczenie (aka semantyka) programu bez powodowania niezamierzonych skutków ubocznych. Istnieje nieodłączne napięcie między wyrażaniem znaczenia a unikaniem niezamierzonych efektów, a napięcie to faktycznie wywodzi się z twierdzeń o niekompletności programowania i naszego wszechświata.
Uproszczenie, nieprecyzyjne technicznie i często dwuznaczne jest definiowanie deklaratywnego jako „ co robić ”, a imperatywnego jako „ jak to zrobić ” . Niejednoznacznym przypadkiem jest „ co ” to „ jak ” w programie, który generuje program - kompilator.
Najwyraźniej nieograniczona rekurencja, która sprawia, że język Turinga jest kompletny , jest również analogicznie w semantyce - nie tylko w składniowej strukturze oceny (czyli semantyce operacyjnej). Jest to logicznie przykład analogiczny do twierdzenia Gödla - „ każdy kompletny system aksjomatów jest również niespójny ”. Zastanów się nad sprzecznością tego cytatu! Jest to także przykład, który pokazuje, w jaki sposób wyrażenie semantyki nie ma możliwego do udowodnienia ograniczenia, dlatego nie możemy udowodnić 2, że program (i analogicznie jego semantyka) zatrzymał aka twierdzenie Haltinga.
Twierdzenia o niekompletności wywodzą się z fundamentalnej natury naszego wszechświata, który, jak stwierdzono w Drugim Prawie Termodynamiki, brzmi „ entropia (czyli # niezależnych możliwości) na zawsze osiąga maksimum ”. Kodowanie i projektowanie programu nigdy się nie kończy - żyje! - ponieważ stara się zaspokoić potrzeby świata rzeczywistego, a semantyka świata rzeczywistego ciągle się zmienia i zyskuje na popularności. Ludzie nigdy nie przestają odkrywać nowych rzeczy (w tym błędów w programach ;-).
Aby precyzyjnie i technicznie uchwycić wyżej wspomniane pożądane pojęcie w tym dziwnym wszechświecie, który nie ma krawędzi (zastanów się, że! Nie ma „na zewnątrz” naszego wszechświata), wymagana jest zwięzła, ale zwodniczo-prosta definicja, która zabrzmi nieprawidłowo, dopóki nie zostanie wyjaśniona głęboko.
Definicja:
Właściwość deklaratywna to miejsce, w którym może istnieć tylko jeden możliwy zestaw instrukcji, które mogą wyrażać każdy konkretny semantyczny moduł.
Właściwością imperatywną 3 jest dualność, w której semantyka jest niespójna w składzie i / lub może być wyrażona za pomocą odmian zestawów instrukcji.
Ta definicja deklaratywna jest wyraźnie lokalna w zakresie semantycznym, co oznacza, że wymaga, aby semantyczny modułowy zachowywał swoje spójne znaczenie niezależnie od tego, gdzie i jak jest tworzony i stosowany w zakresie globalnym . Zatem każdy deklaratywny modułowy semantyczny powinien być z natury ortogonalny dla wszystkich możliwych innych - i nie być niemożliwym (z powodu twierdzeń o niekompletności) globalnym algorytmem lub modelem służącym do obserwowania spójności, co jest również punktem „ Profesora Roberta Harpera „ Więcej nie zawsze jest lepsze ” informatyki na Carnegie Mellon University, jednym z projektantów Standard ML.
Przykłady tej modułowej semantyki deklaratywnej obejmują funktory teorii kategorii, np .
Applicative
Typowanie nominalne, przestrzenie nazw, nazwane pola i wrt do poziomu operacyjnego semantyki, a następnie czystego programowania funkcjonalnego.Tak więc dobrze zaprojektowane języki deklaratywne mogą wyraźniej wyrażać znaczenie , choć z pewną utratą ogólności w tym, co można wyrazić, ale zyskiem w tym, co można wyrazić z wewnętrzną spójnością.
Przykładem wyżej wymienionej definicji jest zestaw formuł w komórkach programu arkusza kalkulacyjnego - które nie powinny mieć takiego samego znaczenia po przeniesieniu do różnych komórek kolumny i wiersza, tj. Zmianie identyfikatorów komórek. Identyfikatory komórek są częścią zamierzonego znaczenia i nie są zbyteczne. Dlatego wynik każdego arkusza kalkulacyjnego jest unikalny dla identyfikatorów komórek w zestawie formuł. Spójnym semantycznym modułem w tym przypadku jest użycie identyfikatorów komórek jako danych wejściowych i wyjściowych funkcji czystych dla formuł komórek (patrz poniżej).
Hyper Text Markup Language, czyli HTML - język statycznych stron internetowych - jest przykładem bardzo (ale nie idealnie 3 ) języka deklaratywnego, który (przynajmniej przed HTML 5) nie był w stanie wyrazić zachowania dynamicznego. HTML jest chyba najłatwiejszym językiem do nauki. W celu zachowania dynamicznego imperatywny język skryptowy, taki jak JavaScript, był zwykle łączony z HTML. HTML bez JavaScript pasuje do deklaratywnej definicji, ponieważ każdy typ nominalny (tj. Tagi) zachowuje swoje spójne znaczenie w składzie zgodnie z regułami składni.
Konkurencyjną definicją deklaratywną są przemienne i idempotentne właściwości instrukcji semantycznych, tzn. Że instrukcje można zmieniać i duplikować bez zmiany znaczenia. Na przykład instrukcje przypisujące wartości do nazwanych pól mogą być ponownie uporządkowane i powielone bez zmiany znaczenia programu, jeśli te nazwy są modularne wrt w dowolnej dorozumianej kolejności. Nazwy czasami sugerują kolejność, np. Identyfikatory komórek obejmują ich pozycję kolumny i wiersza - przeniesienie sumy w arkuszu kalkulacyjnym zmienia jego znaczenie. W przeciwnym razie właściwości te domyślnie wymagają globalnegospójność semantyki. Zasadniczo niemożliwe jest zaprojektowanie semantyki instrukcji, więc pozostają one spójne, jeśli są losowo uporządkowane lub powielane, ponieważ kolejność i duplikacja są nieodłączne od semantyki. Na przykład stwierdzenia „Foo istnieje” (lub konstrukcja) i „Foo nie istnieje” (i zniszczenie). Jeśli weźmie się pod uwagę przypadkową niekonsekwencję endemiczną za zamierzoną semantykę, wówczas uznaje się tę definicję za wystarczająco ogólną dla właściwości deklaratywnej. Zasadniczo definicja ta jest pusta jako definicja uogólniona, ponieważ próbuje ona uczynić spójność ortogonalną względem semantyki, tj. Przeciwstawić się temu, że wszechświat semantyki jest dynamicznie nieograniczony i nie może być ujęty w paradygmacie globalnej spójności.
Wymaganie komutatywnych i idempotentnych właściwości (porządek oceny strukturalnej) semantyki operacyjnej niższego poziomu przekształca semantykę operacyjną w deklaratywną zlokalizowaną modularną semantyczną, np. Czyste programowanie funkcjonalne (w tym rekurencyjne zamiast pętli imperatywnych). Następnie kolejność operacyjna szczegółów implementacji nie wpływa (tj. Rozprzestrzenia się globalnie ) na spójność semantyki wyższego poziomu. Na przykład kolejność oceny (i teoretycznie także powielania) formuł arkusza kalkulacyjnego nie ma znaczenia, ponieważ dane wyjściowe nie są kopiowane do danych wejściowych, dopóki nie zostaną obliczone wszystkie dane wyjściowe, tj. Analogicznie do funkcji czystych.
C, Java, C ++, C #, PHP i JavaScript nie są szczególnie deklaratywne. Składnia Copute'a i Pythona są bardziej deklaratywnie sprzężone z zamierzonymi wynikami , tj. Spójną semantyką składniową, która eliminuje obce, dzięki czemu można łatwo zrozumieć kod po zapomnieniu. Copute i Haskell egzekwują determinizm semantyki operacyjnej i zachęcają do „ nie powtarzania się ” (DRY), ponieważ pozwalają jedynie na paradygmat funkcjonalny.
2 Nawet tam, gdzie możemy udowodnić semantykę programu, np. Za pomocą języka Coq, jest to ograniczone do semantyki wyrażanej podczas pisania , a pisanie nigdy nie może uchwycić całej semantyki programu - nawet w przypadku języków, które są niekompletność Turinga, np. HTML + CSS, można wyrazić niespójne kombinacje, które mają w ten sposób niezdefiniowaną semantykę.
3 Wiele wyjaśnień niesłusznie twierdzi, że tylko programowanie imperatywne ma składniowo uporządkowane instrukcje. Wyjaśniłem to zamieszanie między programowaniem imperatywnym a funkcjonalnym . Na przykład kolejność instrukcji HTML nie zmniejsza spójności ich znaczenia.
Edycja: Zamieściłem następujący komentarz na blogu Roberta Harpera:
w programowaniu funkcjonalnym ... zakres zmienności zmiennej jest typem
W zależności od tego, jak odróżnia się programowanie funkcjonalne od programowania imperatywnego, twoje „przypisywalne” w programie imperatywnym może również mieć typ ograniczający jego zmienność.
Jedyną niezrozumiałą definicją, którą obecnie cenię dla programowania funkcjonalnego, jest: a) funkcje jako obiekty i typy pierwszej klasy, b) preferencja dla rekurencji nad pętlami i / lub c) funkcje czyste - tj. Te funkcje, które nie wpływają na pożądaną semantykę programu po zapamiętywaniu (a zatem całkowicie czyste programowanie funkcjonalne nie istnieje w semantyce denotacyjnej ogólnego przeznaczenia z powodu wpływu semantyki operacyjnej, np. alokacji pamięci ).
Właściwość idempotentna funkcji czystej oznacza, że wywołanie funkcji jej zmiennych można zastąpić jej wartością, co zwykle nie ma miejsca w przypadku argumentów procedury imperatywnej. Funkcje czyste wydają się być deklaratywne w stosunku do nieskomplikowanych przejść stanu między typami danych wejściowych i wyników.
Ale zestaw funkcji czystych nie zachowuje takiej spójności, ponieważ możliwe jest modelowanie procesu imperatywnego skutków ubocznych (stanu globalnego) w czysto funkcjonalnym języku programowania, np. IOMonad Haskella, a ponadto całkowicie niemożliwe jest zapobieganie temu dowolny całkowicie funkcjonalny język programowania Turinga.
Jak napisałem w 2012 r., Który wydaje się podobny do konsensusu komentarzy na twoim niedawnym blogu , to programowanie deklaratywne jest próbą uchwycenia pojęcia, że zamierzona semantyka nigdy nie jest nieprzejrzysta. Przykładami nieprzejrzystej semantyki są zależność od porządku, zależność od usuwania semantyki wyższego poziomu w warstwie semantyki operacyjnej (np. Rzutowania nie są konwersjami, a potwierdzone generyczne ograniczają semantykę wyższego poziomu ) oraz zależność od wartości zmiennych, których nie można sprawdzić (udowodniono poprawne) według języka programowania.
Doszedłem zatem do wniosku, że tylko niekompletne języki mogą być deklaratywne.
Tak więc jednym jednoznacznym i wyraźnym atrybutem języka deklaratywnego może być to, że można udowodnić, że jego wyniki są zgodne z jakimś wymiennym zbiorem reguł generatywnych. Na przykład, dla każdego konkretnego programu HTML (ignorując różnice w sposobie rozbieżności interpretatorów), który nie jest skryptowany (tj. Nie jest kompletny w Turingu), jego zmienność wyjściowa może być policzalna. Lub bardziej zwięźle program HTML jest czystą funkcją jego zmienności. Podobnie program do obsługi arkuszy kalkulacyjnych jest czystą funkcją jego zmiennych wejściowych.
Wydaje mi się więc, że języki deklaratywne są antytezą nieograniczonej rekurencji , tzn. Według drugiego twierdzenia Gödela o samoreferencyjnych twierdzeniach nie można udowodnić.
Lesie Lamport napisała bajkę o tym, jak Euclid mógł obejść twierdzenia Gödela dotyczące niekompletności zastosowane do dowodów matematycznych w kontekście języka programowania przez zgodność między typami i logiką (korespondencja Curry-Howarda itp.).
Programowanie deklaratywne to „czynność programowania w językach zgodnych z modelem mentalnym programisty, a nie z modelem operacyjnym maszyny”.
Różnicę między programowaniem deklaratywnym a imperatywnym dobrze ilustruje problem analizy danych strukturalnych.
Program imperatywny używałby wzajemnie rekurencyjnych funkcji do pobierania danych wejściowych i generowania danych. Program deklaratywny wyraziłby gramatykę, która określa strukturę danych, dzięki czemu można je następnie przeanalizować.
Różnica między tymi dwoma podejściami polega na tym, że program deklaratywny tworzy nowy język, który jest ściślej odwzorowany w modelu mentalnym problemu niż w języku goszczącym.
Wyjaśniłbym to, ponieważ DP to sposób na wyrażenie
... i tam, gdzie istnieje silnik odliczania, zwykle pracujący z algorytmem unifikacji w celu znalezienia celów.
O ile wiem, zaczęto go używać do opisywania systemów programistycznych takich jak Prolog, ponieważ prolog (rzekomo) polega na deklarowaniu rzeczy w abstrakcyjny sposób.
W coraz większym stopniu oznacza to bardzo mało, ponieważ ma definicję podaną przez użytkowników powyżej. Powinno być jasne, że istnieje luka między deklaratywnym programowaniem Haskell, a w stosunku do deklaratywnego programowania HTML.
Kilka innych przykładów programowania deklaratywnego:
Programowanie deklaratywne jest przyjemne, ponieważ może uprościć twój mentalny model * kodu i może być bardziej skalowalne.
Załóżmy na przykład, że masz funkcję, która robi coś z każdym elementem tablicy lub listy. Tradycyjny kod wyglądałby tak:
foreach (object item in MyList)
{
DoSomething(item);
}
Nic wielkiego. Ale co, jeśli użyjesz bardziej deklaratywnej składni i zamiast tego zdefiniujesz DoSomething () jako akcję? Możesz to powiedzieć w ten sposób:
MyList.ForEach(DoSometing);
Jest to oczywiście bardziej zwięzłe. Ale jestem pewien, że masz więcej obaw niż tylko zapisywanie dwóch linii kodu tu i tam. Wydajność, na przykład. Po staremu przetwarzanie musiało być wykonywane po kolei. Co zrobić, jeśli metoda .ForEach () ma sposób zasygnalizować, że może ona automatycznie przetwarzać dane równolegle? Teraz nagle twój kod jest wielowątkowy w bardzo bezpieczny sposób i zmieniłeś tylko jeden wiersz kodu. W rzeczywistości istnieje rozszerzenie .Net, które pozwala to zrobić.
To zależy od tego, jak prześlesz odpowiedź na tekst. Ogólnie rzecz biorąc, możesz spojrzeć na program w pewnym widoku, ale zależy to od tego, pod jakim kątem patrzysz na problem. Zacznę od rozpoczęcia programu: Dim Bus, Car, Time, Height As Integr
Znowu zależy to od ogólnego problemu. Być może będziesz musiał go skrócić z powodu programu. Mam nadzieję, że to pomaga i potrzebuję informacji zwrotnej, jeśli nie. Dziękuję Ci.