Je cherchais sur le Web une définition de la programmation déclarative et impérative qui m'apporterait un peu de lumière. Cependant, le langage utilisé sur certaines des ressources que j'ai trouvées est décourageant - par exemple, sur Wikipedia . Quelqu'un at-il un exemple concret à me montrer qui pourrait apporter une certaine perspective à ce sujet (peut-être en C #)?
LINQ est un excellent exemple de programmation déclarative ou impérative en C #.
Avec impératif programmation, vous indiquez au compilateur ce que vous voulez qu'il se passe, étape par étape.
Par exemple, commençons par cette collection et choisissons les nombres impairs:
List<int> collection = new List<int> { 1, 2, 3, 4, 5 };
Avec la programmation impérative, nous allions de l'avant et décidions ce que nous voulions:
List<int> results = new List<int>();
foreach(var num in collection)
{
if (num % 2 != 0)
results.Add(num);
}
Ici, nous disons:
Avec la programmation déclarative, par contre, vous écrivez un code qui décrit ce que vous voulez, mais pas nécessairement comment l’obtenir (déclarez vos résultats souhaités, mais pas l’étape par étape):
var results = collection.Where( num => num % 2 != 0);
Ici, nous disons "Donnez-nous tout ce qui est étrange", pas "Parcourez la collection. Cochez cet élément, s'il est étrange, ajoutez-le à une collection de résultats."
Dans de nombreux cas, le code sera un mélange des deux conceptions, de sorte qu'il ne sera pas toujours noir et blanc.
La programmation déclarative est quand vous dites quoi vous voulez, et le langage impératif est quand vous dites comment pour obtenir ce que vous voulez.
Un exemple simple en Python:
# Declarative
small_nums = [x for x in range(20) if x < 5]
# Imperative
small_nums = []
for i in range(20):
if i < 5:
small_nums.append(i)
Le premier exemple est déclaratif car nous ne spécifions aucun "détail d'implémentation" lors de la construction de la liste.
Pour associer un exemple en C #, en général, l'utilisation de LINQ donne un style déclaratif, car vous ne dites pas comment pour obtenir ce que vous voulez; vous dites seulement quoi vous voulez. Vous pourriez dire la même chose à propos de SQL.
L'un des avantages de la programmation déclarative est qu'elle permet au compilateur de prendre des décisions qui pourraient donner un meilleur code que ce que vous pourriez créer manuellement. Courir avec l'exemple SQL, si vous aviez une requête comme
SELECT score FROM games WHERE id < 100;
le "compilateur" SQL peut "optimiser" cette requête car il sait que id
est un champ indexé - ou peut-être n'est-il pas indexé, auquel cas il devra quand même itérer sur l'ensemble du jeu de données. Ou peut-être que le moteur SQL sait que c'est le moment idéal pour utiliser les 8 cœurs pour une recherche parallèle rapide. Yo, en tant que programmeur, n'êtes concerné par aucune de ces conditions, et vous n'avez pas à écrire votre code pour gérer un cas particulier de cette manière.
Déclaratif vs impératif
A paradigme de programmation est un style fondamental de la programmation informatique. Il existe quatre principaux paradigmes: impératif, déclaratif, fonctionnel (considéré comme un sous-ensemble du paradigme déclaratif) et orienté objet.
Programmation déclarative : est un paradigme de programmation qui exprime la logique d'un calcul (What do) sans décrire son flux de contrôle (How do). Certains exemples bien connus de langages déclaratifs spécifiques à un domaine (DSL) incluent CSS, les expressions régulières et un sous-ensemble de SQL (requêtes SELECT, par exemple). De nombreux langages de balisage tels que HTML, MXML, XAML, XSLT ... sont souvent déclaratifs. La programmation déclarative essaie de brouiller la distinction entre un programme en tant qu'ensemble d'instructions et un programme en tant qu'affirmation de la réponse souhaitée.
Programmation impérative : est un paradigme de programmation qui décrit le calcul en termes d’énoncés modifiant le statut d’un programme. Les programmes déclaratifs peuvent être considérés à la fois comme des commandes de programmation ou des assertions mathématiques.
Programmation fonctionnelle: est un paradigme de programmation qui considère le calcul comme une évaluation de fonctions mathématiques et évite les données d’état et mutables. Il met l'accent sur l'application de fonctions, contrairement au style de programmation impératif, qui met l'accent sur les changements d'état. Dans un langage purement fonctionnel, tel que Haskell, toutes les fonctions sont sans effets secondaires et les changements d'état ne sont représentés que comme des fonctions transformant l'état.
L'exemple suivant de programmation impérative dans MSDN , parcourt les nombres de 1 à 10 et trouve les nombres pairs.
var numbersOneThroughTen = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//With imperative programming, we'd step through this, and decide what we want:
var evenNumbers = new List<int>();
foreach (var number in numbersOneThroughTen)
{ if (number % 2 == 0)
{
evenNumbers.Add(number);
}
}
//The following code uses declarative programming to accomplish the same thing.
// Here, we're saying "Give us everything where it's odd"
var evenNumbers = numbersOneThroughTen.Select(number => number % 2 == 0);
Les deux exemples donnent le même résultat, et l’un n’est ni meilleur ni pire que l’autre. Le premier exemple nécessite plus de code, mais le code est testable et l'approche impérative vous permet de contrôler totalement les détails de la mise en œuvre. Dans le deuxième exemple, le code est sans doute plus lisible; Cependant, LINQ ne vous permet pas de contrôler ce qui se passe dans les coulisses. Vous devez avoir la certitude que LINQ fournira le résultat demandé.
J'ajouterai un autre exemple qui apparaît rarement dans les discussions sur la programmation déclarative/impérative: l'interface utilisateur!
En C #, vous pouvez créer une interface utilisateur à l'aide de différentes technologies.
À la fin impérative, vous pouvez utiliser DirectX ou OpenGL pour dessiner très impérativement vos boutons, cases à cocher, etc. C'est à vous de dire comment dessiner l'interface utilisateur.
À la fin déclarative, vous avez WPF. Vous écrivez un peu de XML (ouais, ouais, "XAML" techniquement) et le framework fait le travail pour vous. Vous dites à quoi ressemble l'interface utilisateur. C'est au système de déterminer comment le faire.
Quoi qu'il en soit, juste une autre chose à penser. Ce n’est pas parce qu’une langue est déclarative ou impérative qu’elle ne présente pas certaines caractéristiques de l’autre.
En outre, l'un des avantages de la programmation déclarative est que son objectif est généralement plus facile à comprendre à la lecture du code, alors que l'impératif vous donne un contrôle plus précis sur l'exécution.
L'essentiel de tout ça:
Déclaratif -> what
que vous voulez faire
Impératif -> how
vous voulez le faire
Toutes les réponses ci-dessus et d'autres publications en ligne mentionnent les suivantes:
Ce qu'ils ne nous ont pas dit, c'est comment l'obtenir. Pour qu'une partie du programme soit plus déclarative, les autres parties doivent fournir l'abstraction pour masquer les détails de la mise en oeuvre (qui sont les codes impératif).
list.Where()
pour obtenir une nouvelle liste filtrée. Pour que cela fonctionne, Microsoft a fait le gros du travail derrière l’abstraction de LINQ.En fait, l’une des raisons pour lesquelles la programmation fonctionnelle et les bibliothèques fonctionnelles sont plus déclaratives, c’est parce qu’elles ont résumé les boucles et les créations de listes, masquant tous les détails de l’implémentation (des codes impératifs avec des boucles).
Dans tout programme, vous aurez toujours à la fois des codes impératifs et des codes déclaratifs. Ce que vous devez viser est de cacher tous les codes impératif derrière les abstractions, afin que les autres parties du programme puissent les utiliser de manière déclarative.
Enfin, bien que la programmation fonctionnelle et LINQ puissent rendre votre programme plus déclaratif, vous pouvez toujours le rendre encore plus déclaratif en fournissant davantage d’abstractions. Par exemple:
// JavaScript example
// Least declarative
const bestProducts = [];
for(let i = 0; i < products.length; i++) {
let product = products[i];
if (product.rating >= 5 && product.price < 100) {
bestProducts.Push(product);
}
}
// More declarative
const bestProducts = products.filter(function(product) {
return product.rating >= 5 && product.price < 100;
});
// Most declarative, implementation details are hidden in a function
const bestProducts = getBestProducts();
J'ai aimé une explication d'un cours de Cambridge + leurs exemples:
int x;
- quoi (déclaratif)x=x+1;
- commentLa programmation impérative exige des développeurs qu'ils définissent pas à pas la manière dont le code doit être exécuté. Pour donner des instructions impératives, vous dites: "Allez dans la 1re rue, tournez à gauche sur Main, conduisez deux rues, tournez à droite sur Maple et arrêtez-vous à la troisième maison à gauche." La version déclarative pourrait ressembler à ceci: : "Conduisez chez Sue." On dit comment faire quelque chose; l'autre dit ce qu'il faut faire.
Le style déclaratif présente deux avantages par rapport au style impératif:
- Cela ne force pas le voyageur à mémoriser une longue série d'instructions.
- Il permet au voyageur d’optimiser l’itinéraire lorsque cela est possible.
Calvert, C Kulkarni, D (2009). LINQ essentiel. Addison Wesley. 48.
La différence a principalement à voir avec le niveau global d'abstraction. Avec déclaration, à un moment donné, vous êtes si loin des étapes individuelles que le programme a beaucoup de latitude pour obtenir votre résultat.
Vous pouvez considérer chaque instruction comme se situant quelque part dans un continuum:
Degré d'abstraction:
Declarative <<=====|==================>> Imperative
Exemple du monde réel déclaratif:
Exemple impératif du monde réel:
La programmation impérative consiste à dire explicitement à l’ordinateur ce qu’il doit faire et comment le faire, comme spécifier l’ordre et autres.
C #:
for (int i = 0; i < 10; i++)
{
System.Console.WriteLine("Hello World!");
}
Déclaratif est quand vous dites à l'ordinateur quoi faire, mais pas vraiment comment le faire. Datalog/Prolog est le premier langage qui nous vient à l’esprit à cet égard. Fondamentalement, tout est déclaratif. Vous ne pouvez pas vraiment garantir l'ordre.
C # est un langage de programmation beaucoup plus impératif, mais certaines fonctionnalités de C # sont plus déclaratives, comme Linq
dynamic foo = from c in someCollection
let x = someValue * 2
where c.SomeProperty < x
select new {c.SomeProperty, c.OtherProperty};
La même chose pourrait être écrite impérativement:
dynamic foo = SomeCollection.Where
(
c => c.SomeProperty < (SomeValue * 2)
)
.Select
(
c => new {c.SomeProperty, c.OtherProperty}
)
(exemple de wikipedia Linq)
En informatique, la programmation déclarative est un paradigme de programmation qui exprime la logique d’un calcul sans décrire son flux de contrôle.
De http://en.wikipedia.org/wiki/Declarative_programming
en un mot, le langage déclaratif est plus simple car il manque la complexité du flux de contrôle (boucles, instructions if, etc.)
Une bonne comparaison est le modèle ASP.Net 'code-behind'. Vous avez des fichiers '.ASPX' déclaratifs, puis les fichiers de code 'ASPX.CS' impératifs. Je trouve souvent que si je peux faire tout ce dont j'ai besoin dans la moitié déclarative du script, beaucoup plus de personnes peuvent suivre ce qui se fait.
Voler de Philip Roberts ici :
Deux exemples:
1. Doubler tous les nombres d'un tableau
Impérativement:
var numbers = [1,2,3,4,5]
var doubled = []
for(var i = 0; i < numbers.length; i++) {
var newNumber = numbers[i] * 2
doubled.Push(newNumber)
}
console.log(doubled) //=> [2,4,6,8,10]
Déclarativement:
var numbers = [1,2,3,4,5]
var doubled = numbers.map(function(n) {
return n * 2
})
console.log(doubled) //=> [2,4,6,8,10]
2. Résumer tous les éléments d'une liste
Impérativement
var numbers = [1,2,3,4,5]
var total = 0
for(var i = 0; i < numbers.length; i++) {
total += numbers[i]
}
console.log(total) //=> 15
De manière déclarative
var numbers = [1,2,3,4,5]
var total = numbers.reduce(function(sum, n) {
return sum + n
});
console.log(total) //=> 15
Notez que les exemples impératifs impliquent la création d’une nouvelle variable, sa mutation et le renvoi de cette nouvelle valeur (comment faire bouger les choses), alors que les exemples déclaratifs s’exécutent sur une entrée donnée et renvoient la nouvelle valeur en fonction de l’entrée initiale (ie , ce que nous voulons arriver).
Programmation impérative
Langage de programmation qui requiert une discipline de programmation telle que C/C++, Java, COBOL, FORTRAN, Perl et JavaScript. Les programmeurs écrivant dans de tels langages doivent développer un ordre correct d'actions afin de résoudre le problème, en se basant sur une connaissance du traitement et de la programmation des données.
Programmation déclarative
Langage informatique ne nécessitant pas l’écriture d’une logique de programmation traditionnelle; Les utilisateurs se concentrent sur la définition des entrées et des sorties plutôt que sur les étapes de programme requises dans un langage de programmation procédural tel que C++ ou Java.
Les exemples de programmation déclarative sont CSS, HTML, XML, XSLT, RegX.
Je me demande simplement pourquoi personne n'a mentionné les classes d'attributs en tant qu'outil de programmation déclarative en C #. La réponse populaire de cette page vient de parler de LINQ en tant qu'outil de programmation déclarative.
Selon Wikipedia
Les langages déclaratifs courants comprennent ceux des langages de requête de base de données (SQL, XQuery, par exemple), des expressions régulières, de la programmation logique, de la programmation fonctionnelle et des systèmes de gestion de la configuration.
Donc, LINQ, en tant que syntaxe fonctionnelle, est certainement une méthode déclarative, mais les classes d'attributs en C #, en tant qu'outil de configuration, sont également déclaratives. Voici un bon point de départ pour en savoir plus à ce sujet: Présentation rapide de la programmation d'attributs C #
le programme déclaratif n’est qu’une donnée pour son implémentation/vm impérative plus ou moins "universelle".
avantages: spécifier uniquement une donnée, dans un format codé en dur (et coché), est plus simple et moins sujet aux erreurs que de spécifier directement la variante d'un algorithme impératif. Certaines spécifications complexes ne peuvent tout simplement pas être écrites directement, seulement sous une forme DSL. best et freq utilisés dans les structures de données DSL sont des ensembles et des tables. parce que vous n'avez pas de dépendances entre éléments/lignes. et quand vous n'avez pas de dépendance, vous avez la liberté de modifier et de faciliter le support. (comparez par exemple les modules avec les classes - avec les modules que vous aimez et avec les classes, vous avez un problème de classe de base fragile) toutes les marchandises de déclaration et DSL découlent immédiatement des avantages de ces structures de données (tables et ensembles). autre avantage: vous pouvez modifier l’implémentation du langage déclaratif vm, si DSL est plus ou moins abstrait (bien conçu). faire une mise en œuvre parallèle, par exemple. ou portez-le sur un autre système d'exploitation, etc. de bonnes interfaces ou protocoles d'isolation modulaires bien spécifiés vous procurent une telle liberté et une telle facilité de prise en charge.
inconvénients: vous devinez bien. générique (et paramétré par DSL), l’implémentation impérative de l’algorithme/vm peut être plus lente et/ou gourmande en mémoire que celle spécifiée. dans certains cas. si ce cas est rare - oubliez-le, laissez-le être lent. si c'est fréquent, vous pouvez toujours étendre votre DSL/vm à ce cas. quelque part ralentir tous les autres cas, bien sûr ...
P.S. Les cadres sont à mi-chemin entre DSL et impératif. et comme toutes les solutions intermédiaires, elles combinent des carences et non des avantages. ils ne sont pas si sûrs ET pas si vite :) regardez haskell le touche-à-tout - c'est à mi-chemin entre le fort simple ML et le métaprog flexible Prolog et ... quel monstre c'est. vous pouvez regarder Prolog comme un Haskell avec des fonctions/prédicats booléens uniquement. et quelle simplicité sa flexibilité est contre Haskell ...
Juste pour ajouter un autre exemple en termes de développement d'applications mobiles. Dans iOS et Android, nous avons des constructeurs d'interface, où nous pouvons définir l'interface utilisateur des applications.
L'interface utilisateur dessinée à l'aide de ces générateurs est de nature déclarative, par laquelle on fait glisser les composants. Le dessin réel se déroule en dessous et est exécuté par le framework et le système.
Mais nous pouvons également dessiner tous les composants dans le code, ce qui est impératif par nature.
En outre, certains nouveaux langages tels que Angular JS se concentrent sur la conception déclarative des interfaces utilisateur et nous pouvons voir que de nombreux autres langages offrent le même support. Comme Java, _ n'a pas de méthode déclarative efficace pour dessiner des applications de bureau natives dans Java swing ou Java FX, mais pourrait le faire dans un proche avenir.
De mon point de vue, les deux termes ont des racines en philosophie, il existe des types de connaissances déclaratives et impératives. Les connaissances déclaratives sont des affirmations de vérité, des déclarations de faits comme des axiomes mathématiques. Cela vous dit quelque chose. La connaissance impérative ou procédurale vous indique étape par étape comment arriver à quelque chose. C'est ce que la définition d'un algorithme est essentiellement. Si vous le souhaitez, comparez un langage de programmation informatique avec la langue anglaise. Les phrases déclaratives disent quelque chose. Un exemple ennuyeux, mais voici une manière déclarative d'afficher si deux nombres sont égaux, en Java:
public static void main(String[] args)
{
System.out.print("4 = 4.");
}
Les phrases impératives en anglais, par contre, donnent un ordre ou font une sorte de requête. La programmation impérative n'est donc qu'une liste de commandes (faites ceci, faites cela). Voici un moyen impératif d'afficher si deux nombres sont égaux ou non lors de l'acceptation d'une entrée utilisateur, en Java:
private static Scanner input;
public static void main(String[] args)
{
input = new Scanner(System.in);
System.out.println();
System.out.print("Enter an integer value for x: ");
int x = input.nextInt();
System.out.print("Enter an integer value for y: ");
int y = input.nextInt();
System.out.println();
System.out.printf("%d == %d? %s\n", x, y, x == y);
}
Essentiellement, la connaissance déclarative saute certains éléments pour former une couche d’abstraction sur ces éléments. La programmation déclarative fait la même chose.