Cos'è la programmazione dichiarativa? [chiuso]


193

Continuo a sentire questo termine gettato in giro in diversi contesti. Che cos'è?


7
La risposta selezionata come corretta (indicata dal segno di spunta verde) non è corretta. Non definisce ciò che distingue la programmazione dichiarativa dalla sua antitesi: la programmazione imperativa. Si prega di considerare di cambiare la selezione.
Shelby Moore III,

3
Sì, la risposta contrassegnata come corretta NON è corretta.
Dermot

4
@ShelbyMooreIII Specifica anche quale risposta è corretta per poterla leggere!
vivek.m

@ vivek.m Oggi ho fornito una nuova risposta .
Shelby Moore III,

Risposte:


148

La programmazione dichiarativa avviene quando si scrive il codice in modo tale da descrivere ciò che si desidera fare e non il modo in cui lo si desidera. È lasciato al compilatore per capire come.

Esempi di linguaggi di programmazione dichiarativi sono SQL e Prolog.


29
Devi ancora capire "come" dire al computer "cosa" vuoi :)
hasen

7
@hasenj questo e le altre risposte non definiscono l' unico attributo non condiviso con la programmazione imperativa - che è l' immutabilità .
Shelby Moore III,

3
Sarà davvero fantastico se puoi menzionare come sia diverso dalla programmazione imperativa (linguaggi come C, C ++, C #), quindi sarà più facile per i lettori capire la differenza.
RBT

1
programmatore : "Voglio viaggiare a Parigi". dichiarativo (c) : "Come ti piacerebbe arrivarci? navigare in barca? o volare in aereo? forse, navigare a metà strada e poi volare fino in fondo?" programmatore : "Non ho interesse per come è fatto." imperativo (sql) : "Non preoccuparti. Posso fare una richiesta per quello che ti serve." ( questo è il modo in cui capisco la risposta )
nate

Come può SQL essere dichiarativo se supporta espressioni che non sono referenzialmente trasparenti?
java-addict301,

80

Le altre risposte fanno già un lavoro fantastico spiegando cos'è la programmazione dichiarativa, quindi fornirò solo alcuni esempi del perché ciò potrebbe essere utile.

Indipendenza dal contesto

I programmi dichiarativi sono indipendenti dal contesto . Poiché dichiarano solo l'obiettivo finale, ma non i passaggi intermedi per raggiungere tale obiettivo, lo stesso programma può essere utilizzato in contesti diversi. Questo è difficile da fare con i programmi imperativi , perché spesso dipendono dal contesto (ad esempio lo stato nascosto).

Prendi yacccome esempio. È un generatore di parser aka. compilatore compilatore, un DSL dichiarativo esterno per la descrizione della grammatica di una lingua, in modo che un parser per quella lingua possa essere generato automaticamente dalla descrizione. A causa della sua indipendenza dal contesto, puoi fare molte cose diverse con una tale grammatica:

  • Genera un parser C per quella grammatica (il caso d'uso originale per yacc)
  • Genera un parser C ++ per quella grammatica
  • Genera un parser Java per quella grammatica (usando Jay)
  • Genera un parser C # per quella grammatica (usando GPPG)
  • Genera un parser Ruby per quella grammatica (usando Racc)
  • Genera una visualizzazione ad albero per quella grammatica (usando GraphViz)
  • fai semplicemente un po 'di bella stampa, formattazione elaborata ed evidenziazione della sintassi del file sorgente yacc stesso e includilo nel tuo Manuale di riferimento come una specifica sintattica della tua lingua

E molti altri …

Ottimizzazione

Dato che non prescrivi al computer quali passi adottare e in quale ordine, può riorganizzare il tuo programma molto più liberamente, magari anche eseguire alcune attività in parallelo. Un buon esempio è un pianificatore di query e un ottimizzatore di query per un database SQL. La maggior parte dei database SQL consente di visualizzare la query che stanno effettivamente eseguendo rispetto alla query che è stata richiesta loro di eseguire. Spesso quelle domande non sembrano nullaPiacersi l'un l'altro. Il pianificatore di query tiene conto di cose che non avresti nemmeno immaginato: la latenza di rotazione del piatto del disco, ad esempio o il fatto che un'applicazione completamente diversa per un utente completamente diverso abbia appena eseguito una query simile e la tabella che sei partecipare con e che hai lavorato così duramente per evitare il caricamento è già in memoria comunque.

C'è un interessante compromesso qui: la macchina deve lavorare di più per capire come fare qualcosa di quanto lo sarebbe in un linguaggio imperativo, ma quando si fa capire, ha molta più libertà e molte altre informazioni per l'ottimizzazione palcoscenico.


23

liberamente:

La programmazione dichiarativa tende a:

  • Insiemi di dichiarazioni o dichiarazioni dichiarative, ognuna delle quali ha un significato (spesso nel dominio del problema) e può essere compresa in modo indipendente e isolato.

La programmazione imperativa tende a:

  • Sequenze di comandi, ognuna delle quali esegue alcune azioni; ma che possono o meno avere significato nel dominio problematico.

Di conseguenza, uno stile imperativo aiuta il lettore a comprendere la meccanica di ciò che il sistema sta effettivamente facendo, ma può fornire una scarsa comprensione del problema che intende risolvere. D'altro canto, uno stile dichiarativo aiuta il lettore a comprendere il dominio del problema e l'approccio che il sistema adotta per risolvere il problema, ma è meno informativo sulla questione della meccanica.

I programmi reali (anche quelli scritti in lingue che favoriscono le estremità dello spettro, come ProLog o C) tendono ad avere entrambi gli stili presenti a vari livelli in vari punti, per soddisfare le diverse complessità e le esigenze di comunicazione del pezzo. Uno stile non è superiore all'altro; servono solo a scopi diversi e, come in molte cose della vita, la moderazione è la chiave.


Questa è la risposta corretta Nessuno di questi mormori sopra
Krzysztof Wende,

Grazie per non solo aver risposto alla domanda, ma averlo fatto in stile "Spiega come se fossi 5" con contesto e praticità. Risposta eccellente.
Monsto

17

Ecco un esempio

Nel CSS (usato per dare uno stile alle pagine HTML), se vuoi che un elemento immagine sia alto 100 pixel e largo 100 pixel, devi semplicemente "dichiarare" che è quello che vuoi come segue:

#myImageId {
height: 100px;
width: 100px;
}

Puoi considerare CSS un linguaggio "foglio di stile" dichiarativo.

Il motore del browser che legge e interpreta questo CSS è libero di far apparire l'immagine così alta e così ampia come vuole. Diversi motori di browser (ad esempio, il motore per IE, il motore per Chrome) implementeranno questa attività in modo diverso.

Le loro implementazioni uniche, ovviamente, NON sono scritte in un linguaggio dichiarativo ma in un linguaggio procedurale come Assembly, C, C ++, Java, JavaScript o Python. Tale codice è un insieme di passaggi da eseguire passo dopo passo (e potrebbe includere chiamate di funzione). Potrebbe fare cose come interpolare i valori dei pixel e renderizzarli sullo schermo.


11

Mi dispiace, ma non sono d'accordo con molte altre risposte. Vorrei porre fine a questo confuso fraintendimento della definizione di programmazione dichiarativa.

Definizione

La trasparenza referenziale (RT) delle sottoespressioni è l' unico attributo richiesto di un'espressione di programmazione dichiarativa , poiché è l'unico attributo che non è condiviso con la programmazione imperativa.

Altri attributi citati di programmazione dichiarativa, derivano da questo RT. Fare clic sul collegamento ipertestuale sopra per la spiegazione dettagliata.

Esempio di foglio di calcolo

Due risposte menzionavano la programmazione di fogli di calcolo. Nei casi in cui la programmazione del foglio di calcolo (ovvero le formule) non accede allo stato globale mutabile , si tratta di programmazione dichiarativa. Questo perché i valori delle celle mutabili sono l' input e l' output monolitici dimain() (l'intero programma). I nuovi valori non vengono scritti nelle celle dopo l'esecuzione di ciascuna formula, quindi non sono mutabili per la durata del programma dichiarativo (esecuzione di tutte le formule nel foglio di calcolo). Pertanto, l'una rispetto all'altra, le formule considerano queste cellule mutabili come immutabili. Una funzione RT è autorizzata ad accedere allo stato globale immutabile (e anche allo stato locale mutabile ).

Pertanto, la capacità di mutare i valori nelle celle al termine del programma (come output da main() ), non li rende valori archiviati mutabili nel contesto delle regole. La distinzione chiave è che i valori delle celle non vengono aggiornati dopo l'esecuzione di ciascuna formula del foglio di calcolo, quindi l'ordine di esecuzione delle formule non ha importanza. I valori delle celle vengono aggiornati dopo che sono state eseguite tutte le formule dichiarative.


1
Effetti collaterali involontari possono distruggere la relazione tra ciò che è stato dichiarato e il comportamento effettivo del programma. L'ho spiegato in modo più dettagliato in una nuova risposta .
Shelby Moore III,

8

La programmazione dichiarativa è l'immagine, dove la programmazione imperativa è le istruzioni per dipingere quell'immagine.

Stai scrivendo in uno stile dichiarativo se stai "raccontando quello che è", piuttosto che descrivere i passi che il computer dovrebbe prendere per arrivare dove vuoi.

Quando usi XML per contrassegnare i dati, stai utilizzando la programmazione dichiarativa perché stai dicendo "Questa è una persona, che è un compleanno e laggiù c'è un indirizzo".

Alcuni esempi di dove la programmazione dichiarativa e imperativa si combinano per un maggiore effetto:

  • Windows Presentation Foundation utilizza la sintassi XML dichiarativa per descrivere l'aspetto di un'interfaccia utente e quali sono le relazioni (associazioni) tra controlli e strutture di dati sottostanti.

  • I file di configurazione strutturata utilizzano la sintassi dichiarativa (semplice come le coppie "chiave = valore") per identificare il significato di una stringa o valore di dati.

  • L'HTML contrassegna il testo con tag che descrivono il ruolo di ciascun pezzo di testo rispetto all'intero documento.


2
Sebbene XML sia dichiarativo, non vorrei spingermi fino al punto di dire che è una programmazione dichiarativa semplicemente perché non ci sono semantiche attive associate al markup. Dire che qualcosa è un indirizzo non aiuta a capire cosa vuoi fare con esso.
HenryR,

1
Ci deve essere un contesto sottostante (dominio?) In cui viene utilizzato il programma dichiarativo. Quindi l'uso di XML combinato con ANT può essere interpretato come un programma dichiarativo.
Gutzofter,

7

La programmazione dichiarativa sta programmando con dichiarazioni, cioè frasi dichiarative. Le frasi dichiarative hanno una serie di proprietà che le distinguono dalle frasi imperative. In particolare, le dichiarazioni sono:

  • commutativo (può essere riordinato)
  • associativo (può essere raggruppato)
  • idempotente (può ripetere senza cambiare significato)
  • monotonico (le dichiarazioni non sottraggono informazioni)

Un punto rilevante è che queste sono tutte proprietà strutturali e sono ortogonali all'oggetto. Dichiarativo non riguarda "What vs. How" . Possiamo dichiarare (rappresentare e vincolare) un "come" con la stessa facilità con cui dichiariamo un "cosa" . Dichiarativo riguarda la struttura, non il contenuto.La programmazione dichiarativa ha un impatto significativo sul modo in cui astraggiamo e refattorizziamo il nostro codice e su come lo modularizziamo in sottoprogrammi, ma non tanto sul modello di dominio.

Spesso, possiamo convertire da imperativo a dichiarativo aggiungendo il contesto. Ad esempio da "Svoltare a sinistra. (... attendere ...) Svoltare a destra." a "Bob girerà a sinistra all'incrocio tra Foo e Bar alle 11:01. Bob girerà a destra all'incrocio tra Bar e Baz alle 11:06." Si noti che in quest'ultimo caso le frasi sono idempotenti e commutative, mentre nel primo caso riordinare o ripetere le frasi cambierebbe gravemente il significato del programma.

Per quanto riguarda la monotonia , le dichiarazioni possono aggiungere vincoli che sottraggono possibilità . Ma i vincoli aggiungono ancora informazioni (più precisamente, i vincoli sono informazioni). Se abbiamo bisogno di dichiarazioni variabili nel tempo, è tipico modellarlo con una semantica temporale esplicita, ad esempio da "la palla è piatta" a "la palla è piatta al momento T". Se abbiamo due dichiarazioni contraddittorie, abbiamo un sistema dichiarativo incoerente, sebbene ciò possa essere risolto introducendo vincoli morbidi (priorità, probabilità, ecc.) O sfruttando una logica paraconsistente.


1
Le espressioni dichiarative contribuiscono al comportamento previsto del programma, l'imperativo può contribuire a ciò che è intenzionale o involontario. Dichiarativo non deve essere commutativo e idempotente, se questa è semantica intenzionale.
Shelby Moore III,

6

Descrivere a un computer ciò che vuoi, non come fare qualcosa.


6

immagina una pagina eccellente. Con colonne popolate con formule per calcolare la dichiarazione dei redditi.

Tutta la logica è dichiarata nelle celle, l'ordine del calcolo è determinato dalla formula stessa anziché proceduralmente.

Questo è una specie di programmazione dichiarativa. Dichiarare lo spazio problematico e la soluzione anziché il flusso del programma.

Prolog è l'unico linguaggio dichiarativo che ho usato. Richiede un diverso tipo di pensiero, ma è bene imparare se solo per esporti a qualcosa di diverso dal tipico linguaggio di programmazione procedurale.


6

Ho affinato la mia comprensione della programmazione dichiarativa, da dicembre 2011, quando ho fornito una risposta a questa domanda. Qui segue la mia attuale comprensione.

La versione lunga della mia comprensione (ricerca) è dettagliata a questo link , che dovresti leggere per ottenere una profonda comprensione del sommario che fornirò di seguito.

La programmazione imperativa è dove lo stato mutabile è memorizzato e letto, quindi l'ordinamento e / o la duplicazione delle istruzioni del programma possono alterare il comportamento (semantica) del programma (e persino causare un bug, cioè un comportamento non intenzionale).

Nel senso più ingenuo ed estremo (che ho affermato nella mia precedente risposta), la programmazione dichiarativa (DP) evita tutti gli stati mutabili memorizzati, quindi l'ordinamento e / o la duplicazione delle istruzioni del programma NON possono alterare il comportamento (semantica) del programma .

Tuttavia, una definizione così estrema non sarebbe molto utile nel mondo reale, poiché quasi tutti i programmi prevedono uno stato mutabile memorizzato. Il esempio del foglio di calcolo conforme a questa definizione estrema di DP, poiché l'intero codice del programma viene eseguito fino al completamento con una copia statica dello stato di input, prima che i nuovi stati vengano memorizzati. Quindi se uno stato viene modificato, questo viene ripetuto. Ma la maggior parte dei programmi del mondo reale non può essere limitata a un modello monolitico di cambiamenti di stato.

Una definizione più utile di DP è che l'ordinamento e / o la duplicazione delle istruzioni di programmazione non alterano alcuna semantica opaca. In altre parole, non si verificano cambiamenti casuali nascosti nella semantica: qualsiasi cambiamento nell'ordine delle istruzioni del programma e / o nella duplicazione causa solo cambiamenti intenzionali e trasparenti al comportamento del programma.

Il prossimo passo sarebbe quello di parlare di quali modelli di programmazione o paradigmi aiutano in DP, ma non è questa la domanda qui.


Aggiornamento: fare riferimento anche alla spiegazione più esaustiva alla mia altra risposta sulla definizione di programmazione dichiarativa.
Shelby Moore III,

Functional programmingè una parola d'ordine in questi giorni che è essenzialmente un sottoinsieme della programmazione dichiarativa. LINQ in linguaggio C # è un elemento di programmazione funzionale quando il linguaggio stesso è imperativo per natura. Quindi C # diventa una sorta di ibrido che va da quella definizione.
RBT

1
Il link compute.com è morto.
Kedar Mhaswade,

5

È un metodo di programmazione basato sulla descrizione di cosa dovrebbe fare o essere qualcosa invece di descrivere come dovrebbe funzionare.

In altre parole, non scrivi algoritmi fatti di espressioni, ma semplicemente layout come vuoi che siano le cose. Due buoni esempi sono HTML e WPF.

Questo articolo di Wikipedia è una buona panoramica: http://en.wikipedia.org/wiki/Declarative_programming


1
Piccoli cavilli. WPF è una libreria, non proprio una lingua o un paradigma. Penso che volessi davvero dire che XAML è un esempio di linguaggio dichiarativo.
Nick,

E come descriveresti la programmazione usando una libreria / framework?
Gutzofter,

Non è corretto affermare che la programmazione dichiarativa non può contenere espressioni. La distinzione chiave è che le espressioni non possono mutare i valori memorizzati .
Shelby Moore III,

HTML non è un linguaggio di programmazione
lud

5

Da quando ho scritto la mia risposta precedente, ho formulato una nuova definizione della proprietà dichiarativa che è citata di seguito. Ho anche definito la programmazione imperativa come doppia proprietà.

Questa definizione è superiore a quella che ho fornito nella mia risposta precedente, perché è concisa ed è più generale. Ma può essere più difficile brontolare, perché le implicazioni dei teoremi di incompletezza applicabili alla programmazione e alla vita in generale sono difficili per gli esseri umani che si muovono intorno.

La spiegazione citata della definizione discute il ruolo della pura programmazione funzionale nella programmazione dichiarativa.

Dichiarativo vs. Imperativo

La proprietà dichiarativa è strana, ottusa e difficile da catturare in una definizione tecnicamente precisa che rimane generale e non ambigua, perché è un'idea ingenua che possiamo dichiarare il significato (alias semantica) del programma senza incorrere in effetti collaterali non intenzionali. Esiste una tensione intrinseca tra espressione di significato ed evitamento di effetti non intenzionali, e questa tensione deriva in realtà dai teoremi di incompletezza della programmazione e del nostro universo.

È un'eccessiva semplificazione, tecnicamente imprecisa, e spesso ambigua definire dichiarativo come " cosa fare " e imperativo come " come fare " . Un caso ambiguo è il " cosa " è il " come " in un programma che genera un programma, un compilatore.

Evidentemente la ricorsione illimitata che completa un linguaggio di Turing , è anche analoga nella semantica, non solo nella struttura sintattica della valutazione (nota anche come semantica operativa). Questo è logicamente un esempio analogo al teorema di Gödel: " qualsiasi sistema completo di assiomi è anche incoerente ". Rifletti sulla stranezza contraddittoria di quella citazione! È anche un esempio che dimostra come l'espressione della semantica non abbia un limite dimostrabile, quindi non possiamo dimostrare 2 che un programma (e analogamente la sua semantica) fermi, noto anche come teorema di Halting.

I teoremi di incompletezza derivano dalla natura fondamentale del nostro universo, che come affermato nella Seconda Legge della Termodinamica è " l'entropia (ovvero il numero di possibilità indipendenti) tende al massimo per sempre ". La codifica e la progettazione di un programma non è mai finita - è viva! - perché tenta di soddisfare un'esigenza del mondo reale e la semantica del mondo reale è in continua evoluzione e tende a più possibilità. Gli umani non smettono mai di scoprire cose nuove (inclusi errori nei programmi ;-).

Per catturare con precisione e tecnicamente questa nozione desiderata di cui sopra in questo strano universo che non ha margini (meditare che! Non esiste un "esterno" del nostro universo), richiede una definizione concisa ma ingannevolmente non semplice che suonerà errata fino a quando non viene spiegata profondamente.

Definizione:


La proprietà dichiarativa è dove esiste una sola serie di istruzioni che può esprimere ogni semantica modulare specifica.

La proprietà imperativa 3 è la doppia, in cui la semantica è incoerente sotto la composizione e / o può essere espressa con variazioni di insiemi di affermazioni.


Questa definizione di dichiarativo è distintamente locale nell'ambito semantico, nel senso che richiede che un semantico modulare mantenga il suo significato coerente indipendentemente da dove e come viene istanziato e impiegato nell'ambito globale . Pertanto ogni semantico modulare dichiarativo dovrebbe essere intrinsecamente ortogonale a tutti gli altri possibili - e non un algoritmo o modello globale impossibile (a causa di teoremi di incompletezza) per testimoniare la coerenza, che è anche il punto di " More Is Not Always Better " di Robert Harper, professore di Informatica alla Carnegie Mellon University, uno dei progettisti di Standard ML.

Esempi di queste semantiche dichiarative modulari includono i teorici delle categorie di funzioni, ad esempio laApplicative tipizzazione nominale, gli spazi dei nomi, i campi nominati e la scrittura a livello operativo della semantica, quindi la pura programmazione funzionale.

Quindi linguaggi dichiarativi ben progettati possono esprimere più chiaramente il significato , anche se con una certa perdita di generalità in ciò che può essere espresso, eppure un guadagno in ciò che può essere espresso con coerenza intrinseca.

Un esempio della suddetta definizione è l'insieme di formule nelle celle di un programma per fogli di calcolo, che non dovrebbero avere lo stesso significato quando vengono spostate in celle di colonne e righe diverse, vale a dire che gli identificatori di celle vengono modificati. Gli identificatori cellulari fanno parte e non superano il significato previsto. Quindi ogni risultato del foglio di calcolo è univoco rispetto agli identificatori di cella in una serie di formule. La semantica modulare coerente in questo caso è l'uso di identificatori di celle come input e output di funzioni pure per le formule di celle (vedi sotto).

Hyper Text Markup Language, noto anche come HTML, il linguaggio delle pagine Web statiche, è un esempio di un linguaggio dichiarativo altamente (ma non perfettamente 3 ) che (almeno prima di HTML 5) non era in grado di esprimere un comportamento dinamico. L'HTML è forse il linguaggio più semplice da imparare. Per un comportamento dinamico, un linguaggio di scripting imperativo come JavaScript era di solito combinato con HTML. L'HTML senza JavaScript si adatta alla definizione dichiarativa perché ogni tipo nominale (ovvero i tag) mantiene il suo significato coerente sotto la composizione all'interno delle regole della sintassi.

Una definizione concorrente per dichiarativo è la proprietà commutativa e idempotente delle affermazioni semantiche, ovvero che le affermazioni possono essere riordinate e duplicate senza modificarne il significato. Ad esempio, le istruzioni che assegnano valori ai campi con nome possono essere riordinate e duplicate senza cambiare il significato del programma, se tali nomi sono modulari scritti in un ordine implicito. I nomi a volte implicano un ordine, ad esempio gli identificatori di cella includono la posizione di colonna e riga: lo spostamento di un totale sul foglio di calcolo ne modifica il significato. Altrimenti, queste proprietà implicitamente richiedono globalecoerenza della semantica. È generalmente impossibile progettare la semantica delle dichiarazioni in modo che rimangano coerenti se ordinate o duplicate casualmente, poiché l'ordine e la duplicazione sono intrinseci alla semantica. Ad esempio, le dichiarazioni "Foo esiste" (o costruzione) e "Foo non esiste" (e distruzione). Se si considera un'incoerenza casuale endemica della semantica prevista, si accetta questa definizione come abbastanza generale per la proprietà dichiarativa. In sostanza questa definizione è vacua come definizione generalizzata perché cerca di rendere la coerenza ortogonale alla semantica, cioè di sfidare il fatto che l'universo della semantica è dinamicamente illimitato e non può essere catturato in un paradigma di coerenza globale .

Richiedere le proprietà commutative e idempotenti per la (semantica di valutazione strutturale della) semantica operativa di livello inferiore converte la semantica operativa in una semantica modulare localizzata dichiarativa , ad esempio pura programmazione funzionale (inclusa la ricorsione invece di loop imperativi). Quindi l'ordine operativo dei dettagli di implementazione non influisce (cioè si diffonde a livello globale ) sulla coerenza della semantica di livello superiore. Ad esempio, l'ordine di valutazione (e teoricamente anche la duplicazione) delle formule del foglio di calcolo non ha importanza perché gli output non vengono copiati negli input fino a quando non sono stati calcolati tutti gli output, vale a dire analoghi alle funzioni pure.

C, Java, C ++, C #, PHP e JavaScript non sono particolarmente dichiarativi. La sintassi di Copute e la sintassi di Python sono accoppiate in modo più dichiarativo ai risultati previsti , ovvero semantica sintattica coerente che elimina l'estraneo in modo da poter comprendere facilmente il codice dopo averlo dimenticato. Copute e Haskell applicano il determinismo della semantica operativa e incoraggiano " non ripetere te stesso " (DRY), perché consentono solo il puro paradigma funzionale.


2 Anche dove possiamo dimostrare la semantica di un programma, ad esempio con la lingua Coq, questo è limitato alla semantica espressa nella digitazione e la digitazione non può mai catturare tutta la semantica di un programma, nemmeno per le lingue che sono non completo di Turing, ad es. con HTML + CSS è possibile esprimere combinazioni incoerenti che hanno quindi una semantica indefinita.

3 Molte spiegazioni affermano erroneamente che solo la programmazione imperativa ha istruzioni sintatticamente ordinate. Ho chiarito questa confusione tra programmazione imperativa e funzionale . Ad esempio, l'ordine delle istruzioni HTML non riduce la coerenza del loro significato.


Modifica: ho pubblicato il seguente commento sul blog di Robert Harper:

nella programmazione funzionale ... l'intervallo di variazione di una variabile è un tipo

A seconda di come si distingue la programmazione funzionale dalla programmazione imperativa, il proprio 'assegnabile' in un programma imperativo può anche avere un tipo che pone un limite alla sua variabilità.

L'unica definizione non confusa che attualmente apprezzo per la programmazione funzionale è a) funzioni come oggetti e tipi di prima classe, b) preferenza per la ricorsione su loop e / o c) funzioni pure - cioè quelle funzioni che non influiscono sulla semantica desiderata del programma quando memorizzato ( quindi una programmazione funzionale perfettamente pura non esiste in una semantica denotazionale per scopi generali a causa degli impatti della semantica operativa, ad es. allocazione della memoria ).

La proprietà idempotente di una funzione pura significa che la chiamata di funzione sulle sue variabili può essere sostituita dal suo valore, il che non è generalmente il caso degli argomenti di una procedura imperativa. Le funzioni pure sembrano essere dichiarative rispetto alle transizioni di stato non poste tra i tipi di input e di risultato.

Ma la composizione di funzioni pure non mantiene tale coerenza, poiché è possibile modellare un processo imperativo di effetti collaterali (stato globale) in un linguaggio di programmazione funzionale puro, ad esempio IOMonad di Haskell e inoltre è del tutto impossibile impedire di farlo in qualsiasi linguaggio di programmazione funzionale puro completo di Turing.

Come ho scritto nel 2012, il che sembra al consenso simile dei commenti nel tuo recente blog , che la programmazione dichiarativa è un tentativo di catturare l'idea che la semantica prevista non è mai opaca. Esempi di semantica opaca sono la dipendenza dall'ordine, la dipendenza dalla cancellazione della semantica di livello superiore a livello di semantica operativa (ad es. I cast non sono conversioni e la generica reificata limita la semantica di livello superiore ) e la dipendenza da valori variabili che non possono essere verificati (dimostrato corretto) dal linguaggio di programmazione.

Pertanto, ho concluso che solo le lingue complete non turing possono essere dichiarative.

Pertanto, un attributo non ambiguo e distinto di un linguaggio dichiarativo potrebbe essere che la sua produzione può essere dimostrata obbedire a un insieme numeroso di regole generative. Ad esempio, per qualsiasi programma HTML specifico (ignorando le differenze nei modi in cui gli interpreti divergono) che non è scritto (ovvero non è Turing completo), la sua variabilità di output può essere enumerabile. O più succintamente un programma HTML è una pura funzione della sua variabilità. Idem un programma per fogli di calcolo è una pura funzione delle sue variabili di input.

Quindi mi sembra che le lingue dichiarative siano l'antitesi della ricorsione illimitata , cioè secondo il secondo teorema di incompletezza di Gödel i teoremi autoreferenziali non possono essere provati.

Lesie Lamport ha scritto una fiaba su come Euclide avrebbe potuto aggirare i teoremi di incompletezza di Gödel applicati alle prove matematiche nel contesto del linguaggio di programmazione mediante la congruenza tra tipi e logica (corrispondenza Curry-Howard, ecc.).


4

La programmazione dichiarativa è "l'atto della programmazione in linguaggi conformi al modello mentale dello sviluppatore piuttosto che al modello operativo della macchina".

La differenza tra programmazione dichiarativa e imperativa è ben illustrata dal problema dell'analisi dei dati strutturati.

Un programma imperativo userebbe funzioni reciprocamente ricorsive per consumare input e generare dati. Un programma dichiarativo esprimerebbe una grammatica che definisce la struttura dei dati in modo che possano essere analizzati.

La differenza tra questi due approcci è che il programma dichiarativo crea un nuovo linguaggio che è più strettamente associato al modello mentale del problema rispetto alla sua lingua ospite.


2

Può sembrare strano, ma aggiungerei Excel (o qualsiasi foglio di calcolo davvero) all'elenco dei sistemi dichiarativi. Un buon esempio di questo è dato qui .


1

Lo spiegherei come DP è un modo di esprimere

  • Un'espressione obiettivo , le condizioni per - quello che stiamo cercando. Ce n'è uno, forse o molti?
  • Alcuni fatti noti
  • Regole che estendono i fatti noti

... e dove esiste un motore di detrazione che di solito lavora con un algoritmo di unificazione per trovare gli obiettivi.


-1

Per quanto ne so, ha iniziato a essere usato per descrivere sistemi di programmazione come Prolog, perché prolog si occupa (presumibilmente) di dichiarare le cose in modo astratto.

Significa sempre molto poco, poiché ha la definizione fornita dagli utenti sopra. Dovrebbe essere chiaro che esiste un abisso tra la programmazione dichiarativa di Haskell, rispetto alla programmazione dichiarativa di HTML.


1
Non c'è "divario tra la programmazione dichiarativa di Haskell, rispetto alla programmazione dichiarativa di HTML", perché l' attributo root della programmazione dichiarativa è l'immutabilità dei valori memorizzati.
Shelby Moore III,

Comunque sia, c'è una discreta differenza tra un linguaggio specifico del dominio che è vincolato anche nei suoi calcoli impliciti, rispetto a un sistema di programmazione completo.
Marcin,

Concordato. La completezza di Turing è ortogonale all'immutabilità dei valori memorizzati. Quindi non dovremmo confonderci con l'attributo dichiarativo vs. imperativo. Grazie per aver pensato a uno degli attributi (completezza di Turing) che possono causare quel "abisso".
Shelby Moore III,

La completezza della svolta richiede solo una ricorsione illimitata . L'immutabilità dei valori memorizzati non impedisce la ricorsione illimitata. Quindi sono attributi ortogonali.
Shelby Moore III,

-2

Un paio di altri esempi di programmazione dichiarativa:

  • Markup ASP.Net per il databinding. Dice semplicemente "riempi questa griglia con questa fonte", per esempio, e la lascia al sistema per come ciò accade.
  • Espressioni Linq

La programmazione dichiarativa è utile perché può aiutare a semplificare il modello mentale * di codice e perché potrebbe eventualmente essere più scalabile.

Ad esempio, supponiamo che tu abbia una funzione che fa qualcosa per ciascun elemento in un array o in un elenco. Il codice tradizionale sarebbe simile al seguente:

foreach (object item in MyList)
{
   DoSomething(item);
}

Nessun grosso problema lì. Ma cosa succede se si utilizza la sintassi più dichiarativa e invece si definisce DoSomething () come un'azione? Quindi puoi dirlo in questo modo:

MyList.ForEach(DoSometing);

Questo è, ovviamente, più conciso. Ma sono sicuro che hai più preoccupazioni rispetto al semplice salvataggio di due righe di codice qua e là. Prestazioni, per esempio. Alla vecchia maniera, l'elaborazione doveva essere eseguita in sequenza. E se il metodo .ForEach () avesse un modo per farti capire che poteva gestire l'elaborazione in parallelo, automaticamente? Ora all'improvviso hai reso il tuo codice multi-thread in un modo molto sicuro e hai cambiato solo una riga di codice. E, in effetti, esiste un'estensione per .Net che ti consente di fare proprio questo.

  • Se segui quel link, ti ​​porta a un post sul blog di un mio amico. L'intero post è un po 'lungo, ma puoi scorrere fino all'intestazione intitolata "The Problem" _ e prenderlo lì senza problemi. *

1
Stai descrivendo la programmazione funzionale, non la programmazione dichiarativa . La programmazione dichiarativa ha l'attributo che non muta i valori memorizzati .
Shelby Moore III,

La programmazione dichiarativa può mutare i valori memorizzati ... è solo che si specifica (si dichiara) ciò che si desidera mutare anziché esattamente come procedere con la sua mutazione. Cos'altro pensi che faccia un'istruzione INSERT o UPDATE di sql in sql?
Joel Coehoorn,

Ti manca il punto che se le tue funzioni non sono pure, gli effetti collaterali involontari possono distruggere la relazione tra ciò che hai dichiarato e il comportamento effettivo del programma. L'ho spiegato in modo più dettagliato in una nuova risposta .
Shelby Moore III,

-3

Dipende da come si invia la risposta al testo. Nel complesso puoi guardare il programma da una certa vista, ma dipende da quale angolazione vedi il problema. Ti inizierò con il programma: Dim Bus, Car, Time, Height As Integr

Ancora una volta dipende da quale sia il problema in generale. Potrebbe essere necessario accorciarlo a causa del programma. Spero che questo aiuti e abbia bisogno del feedback se non lo fa. Grazie.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.