Expression contre déclaration


432

Je demande en ce qui concerne c #, mais je suppose que c'est la même chose dans la plupart des autres langues.

Quelqu'un at-il une bonne définition des expressions et des déclarations et quelles sont les différences?


4
Je trouve la réponse que vous avez choisie ambiguë. Une expression fait aussi quelque chose - elle évalue une valeur. J'ai fourni une réponse non ambiguë.
Shelby Moore III

4
@ShelbyMooreIII - Non ambigu et également faux. La réponse acceptée est formulée de manière informelle, mais cette formulation la rend facile à comprendre - et surtout, la signification qu'elle véhicule est exacte.
Justin Morgan

@JustinMorgan Malheureusement, les définitions de la réponse acceptée sont également manifestement erronées ("évalue à une valeur" / "une ligne de code") pour la plupart des langages contemporains, y compris ceux de type C: les expressions peuvent être utilisées dans des contextes non évalués et les déclarations n'ont rien à voir avec les lignes. Même s'il y a quelques explications, la réponse courte est déroutante et trompeuse.
FrankHB

Réponses:


521

Expression: quelque chose qui correspond à une valeur. Exemple: 1 + 2 / x
Instruction: une ligne de code qui fait quelque chose. Exemple: GOTO 100

Dans les premiers langages de programmation à usage général, comme FORTRAN, la distinction était limpide. À FORTRAN, une déclaration était une unité d'exécution, une chose que vous avez faite. La seule raison pour laquelle elle n'était pas appelée "ligne" était parce qu'elle s'étalait parfois sur plusieurs lignes. Une expression seule ne pouvait rien faire ... vous deviez l'assigner à une variable.

1 + 2 / X

est une erreur dans FORTRAN, car il ne fait rien. Il fallait faire quelque chose avec cette expression:

X = 1 + 2 / X

FORTRAN n'avait pas de grammaire telle que nous la connaissons aujourd'hui - cette idée a été inventée, avec la forme Backus-Naur (BNF), dans le cadre de la définition de l'Algol-60. À ce stade, la distinction sémantique («avoir une valeur» par rapport à «faire quelque chose») était inscrite dans la syntaxe : un type de phrase était une expression, et un autre était une déclaration, et l'analyseur pouvait les distinguer.

Les concepteurs des langages ultérieurs ont brouillé la distinction: ils ont permis aux expressions syntaxiques de faire des choses, et ils ont autorisé les déclarations syntaxiques qui avaient des valeurs. Le premier exemple de langage populaire qui survit encore est C. Les concepteurs de C ont réalisé qu'aucun mal n'était fait si vous étiez autorisé à évaluer une expression et à jeter le résultat. En C, chaque expression syntaxique peut être transformée en une instruction en plaçant simplement un point-virgule à la fin:

1 + 2 / x;

est une déclaration totalement légitime même si absolument rien ne se passera. De même, en C, une expression peut avoir des effets secondaires - elle peut changer quelque chose.

1 + 2 / callfunc(12);

parce callfuncque ça pourrait faire quelque chose d'utile.

Une fois que vous autorisez une expression à être une instruction, vous pouvez tout aussi bien autoriser l'opérateur d'affectation (=) à l'intérieur des expressions. Voilà pourquoi C vous permet de faire des choses comme

callfunc(x = 2);

Cela évalue l'expression x = 2 (en affectant la valeur de 2 à x), puis la transmet (les 2) à la fonction callfunc.

Ce flou des expressions et des instructions se produit dans toutes les dérivées C (C, C ++, C # et Java), qui ont encore quelques instructions (comme while) mais qui permettent à presque toutes les expressions d'être utilisées comme instruction (en affectation C # uniquement, les expressions call, increment et decrement peuvent être utilisées comme des instructions; voir la réponse de Scott Wisniewski ).

Le fait d'avoir deux «catégories syntaxiques» (qui est le nom technique du genre de déclarations et d'expressions) peut entraîner une duplication des efforts. Par exemple, C a deux formes de conditionnel, le formulaire de déclaration

if (E) S1; else S2;

et la forme d'expression

E ? E1 : E2

Et parfois, les gens veulent une duplication qui n'est pas là: en C standard, par exemple, seule une instruction peut déclarer une nouvelle variable locale, mais cette capacité est suffisamment utile pour que le compilateur GNU C fournisse une extension GNU qui permet à une expression de déclarer un variable locale également.

Les concepteurs d'autres langages n'aimaient pas ce type de duplication, et ils ont vu très tôt que si les expressions pouvaient avoir des effets secondaires ainsi que des valeurs, alors la distinction syntaxique entre les déclarations et les expressions n'était pas très utile - alors ils s'en sont débarrassés. . Haskell, Icon, Lisp et ML sont tous des langages qui n'ont pas d'instructions syntaxiques - ils ont seulement des expressions. Même les formes en boucle structurée et conditionnelles de classe sont considérées comme des expressions, et elles ont des valeurs, mais pas très intéressantes.


9
Si je ne vous interprète pas mal ici, vous semblez affirmer que "(setf (troisième foo) 'oie)" est une expression, pas une déclaration, à la fois parce que c'est Lisp, qui "n'a pas de déclarations", et parce que Lisp a plus de dix ans de plus que C, qui était le "premier langage populaire à brouiller les frontières [entre les expressions et les déclarations]". Pourriez-vous m'en expliquer les détails?
cjs

2
@Curt Sampson, avez-vous posé cette question séparément?
Kelly

5
Si je ne me trompe pas, callfunc(x = 2);passe xà callfunc, non 2. Si xest un flotteur, callfunc(float)sera appelé, non callfunc(int). Et en C ++, si vous passez x=yà func, et funcprend une référence et la change, elle change x, non y.
Gabriel

Dans la réponse ci-dessus, il est écrit que "Haskell, ... sont tous des langages qui n'ont pas d'instructions syntaxiques - ils ont seulement des expressions". Je suis curieux de savoir pourquoi la whereclause dans haskell est considérée comme une expression et non comme une déclaration. Learnyouahaskell.com/syntax-in-functions#where
skgbanga

@skgbanga je crois whereest en fait une partie de la déclaration de fonction, pas une expression ou une déclaration.
Akangka

22
  • une expression est tout ce qui donne une valeur: 2 + 2
  • une instruction est l'un des "blocs" de base de l'exécution du programme.

Notez qu'en C, "=" est en fait un opérateur, qui fait deux choses:

  • renvoie la valeur de la sous-expression de droite.
  • copie la valeur de la sous-expression de droite dans la variable sur le côté gauche.

Voici un extrait de la grammaire ANSI C. Vous pouvez voir que C n'a pas beaucoup de types d'instructions différents ... la majorité des instructions dans un programme sont des instructions d'expression, c'est-à-dire une expression avec un point-virgule à la fin.

statement
    : labeled_statement
    | compound_statement
    | expression_statement
    | selection_statement
    | iteration_statement
    | jump_statement
    ;

expression_statement
    : ';'
    | expression ';'
    ;

http://www.lysator.liu.se/c/ANSI-C-grammar-y.html


2
Logique incorrecte sur ce qu'est une déclaration. Un programme déclaratif peut également s'exécuter, mais un programme déclaratif n'a pas d'instructions. Une déclaration est et fait des "effets secondaires" , c'est-à-dire qu'elle est impérative. cf. ma réponse .
Shelby Moore III

15

Une expression est quelque chose qui renvoie une valeur, contrairement à une instruction.

Pour des exemples:

1 + 2 * 4 * foo.bar()     //Expression
foo.voidFunc(1);          //Statement

Le gros problème entre les deux est que vous pouvez enchaîner les expressions, tandis que les déclarations ne peuvent pas être enchaînées.


6
Bien sûr, les déclarations peuvent être enchaînées. {stmt1; stmt2; stmt3;} est une chaîne, et c'est aussi une instruction (composée) elle-même.
Hugh Allen

5
foo.voidFunc(1);est une expression avec une valeur nulle. whileet ifsont des déclarations.
tzot

Je suis curieux de ne pas enchaîner les déclarations. Est-ce que quelque chose comme "if (x> 1) return;" être considéré comme enchaînant deux déclarations ensemble?
Simon Tewsi

1
@SimonTewsi Je crois que le returnest considéré comme une sous-déclaration.
RastaJedi

1
@SimonTewsi L'instruction return ici est implicitement à l'intérieur du bloc de l'instruction if, elle fait donc partie de l'instruction if, pas enchaînée avec elle. Le compilateur nous permet d'omettre les accolades ici, car il s'agit d'un bloc d'une seule ligne.
user2597608

9

Vous pouvez le trouver sur wikipedia , mais les expressions sont évaluées selon une certaine valeur, tandis que les instructions n'ont pas de valeur évaluée.

Ainsi, les expressions peuvent être utilisées dans les instructions, mais pas l'inverse.

Notez que certaines langues (comme Lisp, et je crois que Ruby, et bien d'autres) ne font pas la différence entre déclaration et expression ... dans de telles langues, tout est une expression et peut être enchaîné avec d'autres expressions.


8

Pour une explication des différences importantes dans la composabilité (chaînabilité) des expressions par rapport aux déclarations, ma référence préférée est le prix Turing Award de John Backus, La programmation peut-elle être libérée du style von Neumann? .

Les langages impératifs (Fortran, C, Java, ...) mettent l'accent sur les instructions pour structurer les programmes, et ont des expressions comme une sorte de réflexion après coup. Les langages fonctionnels mettent l'accent sur les expressions. Les langages purement fonctionnels ont des expressions si puissantes que les déclarations peuvent être complètement éliminées.


5

Les expressions peuvent être évaluées pour obtenir une valeur, tandis que les instructions ne renvoient pas de valeur (elles sont de type void ).

Les expressions d'appel de fonction peuvent également être considérées comme des instructions, mais à moins que l'environnement d'exécution n'ait une variable intégrée spéciale pour contenir la valeur renvoyée, il n'y a aucun moyen de la récupérer.

Les langages orientés instructions nécessitent que toutes les procédures soient une liste d'instructions. Les langages orientés expression, qui sont probablement tous les langages fonctionnels, sont des listes d'expressions, ou dans le cas de LISP, une longue expression S qui représente une liste d'expressions.

Bien que les deux types puissent être composés, la plupart des expressions peuvent être composées arbitrairement tant que les types correspondent. Chaque type de déclaration a sa propre façon de composer d'autres déclarations, si elles peuvent tout faire. Pour chaque instruction et si les instructions nécessitent soit une seule instruction, soit que toutes les instructions subordonnées soient placées dans un bloc d'instructions, l'une après l'autre, à moins que les sous-instructions ne permettent leurs propres sous-instructions.

Les instructions peuvent également inclure des expressions, où une expression n'inclut vraiment aucune instruction. Une exception, cependant, serait une expression lambda, qui représente une fonction, et peut donc inclure tout ce qu'une fonction peut exclure à moins que le langage ne permette que des lambdas limités, comme les lambdas à expression unique de Python.

Dans un langage basé sur une expression, tout ce dont vous avez besoin est une seule expression pour une fonction puisque toutes les structures de contrôle renvoient une valeur (beaucoup d'entre elles renvoient NIL). Il n'y a pas besoin d'une instruction de retour car la dernière expression évaluée dans la fonction est la valeur de retour.


Le type d'une instruction est le type inférieur. Voidn'est pas le type inférieur. Voir ma réponse .
Shelby Moore III

1
Le type nul n'est-il pas le type inférieur (valeur unique de null)? Ne serait-ce pas voidplus comme le type d'unité (mais avec sa valeur unique inaccessible)?
Mark Cidade

Si voidest le type de retour d'une fonction qui ne retourne jamais (par exemple une fonction qui throwest une erreur), c'est le type du bas . Sinon, voidc'est le type d'unité . Vous avez raison de dire qu'une instruction qui ne peut pas diverger a le type d'unité. Mais une déclaration qui peut diverger est le type le plus bas. En raison du théorème de l'arrêt, nous ne pouvons généralement pas prouver qu'une fonction ne diverge pas, donc je pense que l'unité est une fiction. Le type inférieur ne peut pas avoir de valeur, il ne peut donc pas avoir une seule valeur de null.
Shelby Moore III

1
En ce qui concerne ce que j'ai dit il y a trois ans, je ne sais pas si je pense toujours aux déclarations comme ayant un type nul ou n'importe quel type vraiment. Dans les langages basés sur des instructions que je connais, seules les valeurs et tout ce qui stocke ou renvoie une valeur (par exemple, les expressions, les variables, les membres et les fonctions) peuvent avoir des types. Je pense généralement au type inférieur comme l'ensemble vide (pas de valeurs) et donc tout ce qui n'existe pas ontologiquement aurait ce type. Une nullvaleur est vraiment une pseudovalue indiquant qu'une référence se réfère à quelque chose qui n'existe pas.
Mark Cidade

1
Mark, j'ai apprécié la rationalité de votre réponse. Vous avez essentiellement retiré les mots de ma bouche Et j'espère qu'il était clair que je vous avouais que vous aviez raison de soulever le point unitaire. Je pense que nous sommes d'accord. Je n'allais pas prendre la peine de mentionner cela, mais il semble que certains ici pensent que je suis négatif. J'essaie juste d'être factuel.
Shelby Moore III

4

Simplement: une expression évalue une valeur, une instruction ne le fait pas.


Alors, que fait une déclaration? Rien?
Shelby Moore III,

1
Il peut faire quelque chose, mais il n'évalue rien. C'est-à-dire que vous ne pouvez pas en affecter le résultat à une variable, alors que vous pouvez le faire avec une expression.
Matthew Schinckel

Et à cet effet, une déclaration doit avoir des effets secondaires, comme l'indique ma réponse fortement votée. Quel autre utilitaire une déclaration pourrait-elle éventuellement avoir? Même si un NO-OP était considéré comme une déclaration (ce n'est qu'une "déclaration" en grammaire mais pas au niveau de la couche sémantique car il est effacé après l'analyse et la sémantique est ce dont nous discutons ici), cela n'expliquerait pas ce que le heck l'utilité générale d'une déclaration est.
Shelby Moore III

1
Les déclarations @ShelbyMooreIII n'ont besoin de rien faire ni d'effets secondaires. par exemple, {}est une déclaration. Mettre le mot entre guillemets effrayants ne change rien à cela. Les instructions sont des constructions syntaxiques avec une sémantique. Il n'y a rien de tel que «la couche sémantique» - vous semblez faire référence à l' exécution . Vous dites que vous essayez d'être précis, mais vous avez échoué. Votre plainte concernant "l'ignorance des électeurs" est pure ad hominem; vous n'avez aucune information sur les états mentaux des downvoters.
Jim Balter

Ouais, tout le monde a tort sauf les malhonnêtes intellectuellement. {}est défini comme une instruction dans la spécification du langage C #.
Jim Balter

4

Certaines choses sur les langages basés sur l'expression:


Le plus important: tout renvoie une valeur


Il n'y a pas de différence entre les accolades et les accolades pour délimiter les blocs de code et les expressions, car tout est une expression. Cela n'empêche cependant pas la portée lexicale: une variable locale pourrait être définie pour l'expression dans laquelle sa définition est contenue et toutes les instructions contenues dans celle-ci, par exemple.


Dans un langage basé sur l'expression, tout renvoie une valeur. Cela peut être un peu étrange au début - Qu'est-ce qui (FOR i = 1 TO 10 DO (print i))revient?

Quelques exemples simples:

  • (1) Retour 1
  • (1 + 1) Retour 2
  • (1 == 1) Retour TRUE
  • (1 == 2) Retour FALSE
  • (IF 1 == 1 THEN 10 ELSE 5) Retour 10
  • (IF 1 == 2 THEN 10 ELSE 5) Retour 5

Quelques exemples plus complexes:

  • Certaines choses, comme certains appels de fonction, n'ont pas vraiment de valeur significative à renvoyer (des choses qui ne produisent que des effets secondaires?). Appeler OpenADoor(), FlushTheToilet()ou TwiddleYourThumbs()renverra une sorte de valeur banale, comme OK, Terminé ou Réussite.
  • Lorsque plusieurs expressions non liées sont évaluées dans une expression plus grande, la valeur de la dernière chose évaluée dans la grande expression devient la valeur de la grande expression. Pour prendre l'exemple de (FOR i = 1 TO 10 DO (print i)), la valeur de la boucle for est "10", elle provoque l' (print i)évaluation de l' expression 10 fois, renvoyant à chaque fois i sous forme de chaîne. La dernière fois grâce aux retours 10, notre réponse finale

Cela nécessite souvent un léger changement de mentalité pour tirer le meilleur parti d'un langage basé sur l'expression, car le fait que tout soit une expression permet de `` mettre en ligne '' beaucoup de choses

Comme exemple rapide:

 FOR i = 1 to (IF MyString == "Hello, World!" THEN 10 ELSE 5) DO
 (
    LotsOfCode
 )

est un remplacement parfaitement valide pour le non basé sur l'expression

IF MyString == "Hello, World!" THEN TempVar = 10 ELSE TempVar = 5 
FOR i = 1 TO TempVar DO
(    
    LotsOfCode  
)

Dans certains cas, la disposition permise par le code basé sur l'expression me semble beaucoup plus naturelle

Bien sûr, cela peut conduire à la folie. Dans le cadre d'un projet de loisir dans un langage de script basé sur l'expression appelé MaxScript, j'ai réussi à trouver cette ligne monstre

IF FindSectionStart "rigidifiers" != 0 THEN FOR i = 1 TO (local rigidifier_array = (FOR i = (local NodeStart = FindsectionStart "rigidifiers" + 1) TO (FindSectionEnd(NodeStart) - 1) collect full_array[i])).count DO
(
    LotsOfCode
)

2

Une instruction est un cas particulier d'une expression, une de voidtype. La tendance des langues à traiter les énoncés différemment pose souvent des problèmes et il serait préférable qu’elles soient correctement généralisées.

Par exemple, en C #, nous avons l' Func<T1, T2, T3, TResult>ensemble surchargé très utile de délégués génériques. Mais nous devons également disposer d'un Action<T1, T2, T3>ensemble correspondant , et la programmation d'ordre supérieur à usage général doit constamment être dupliquée pour faire face à cette malheureuse bifurcation.

Exemple trivial - une fonction qui vérifie si une référence est nulle avant d'appeler sur une autre fonction:

TResult IfNotNull<TValue, TResult>(TValue value, Func<TValue, TResult> func)
                  where TValue : class
{
    return (value == null) ? default(TValue) : func(value);
}

Le compilateur pourrait-il gérer la possibilité de l' TResultêtre void? Oui. Il suffit d'exiger que return soit suivi d'une expression de type void. Le résultat de default(void)serait de type void, et la fonction transmise devrait être de la forme Func<TValue, void>(qui serait équivalente à Action<TValue>).

Un certain nombre d'autres réponses impliquent que vous ne pouvez pas enchaîner des instructions comme vous le pouvez avec des expressions, mais je ne sais pas d'où vient cette idée. Nous pouvons penser à ce ;qui apparaît après les instructions comme un opérateur d'infixe binaire, prenant deux expressions de type voidet les combinant en une seule expression de type void.


Une déclaration n'est pas un cas particulier d'expression. Dans certains langages (c'est-à-dire la plupart des successeurs C), c'est en fait l'inverse.
Akangka

2

Déclarations -> Instructions à suivre séquentiellement
Expressions -> Évaluation qui renvoie une valeur

Les instructions sont fondamentalement comme des étapes ou des instructions dans un algorithme, le résultat de l'exécution d'une instruction est l'actualisation du pointeur d'instruction (appelé assembleur)

Les expressions n'impliquent pas et l'ordre d'exécution à première vue, leur but est d'évaluer et de renvoyer une valeur. Dans les langages de programmation impératifs, l'évaluation d'une expression a un ordre, mais c'est simplement à cause du modèle impératif, mais ce n'est pas leur essence.

Exemples de déclarations:

for
goto
return
if

(tous impliquent le passage de la ligne (instruction) d'exécution à une autre ligne)

Exemple d'expressions:

2+2

(cela n'implique pas l'idée d'exécution, mais l'évaluation)


Et les effets secondaires?
Austin Henley

@AustinHenley il n'y a aucune exigence pour cela. En fait, une expression peut certainement avoir un effet secondaire.
Akangka

1

Statement ,

Une instruction est un bloc de construction procédural à partir duquel tous les programmes C # sont construits. Une instruction peut déclarer une variable ou une constante locale, appeler une méthode, créer un objet ou affecter une valeur à une variable, une propriété ou un champ.

Une série d'instructions entourées d'accolades forment un bloc de code. Un corps de méthode est un exemple de bloc de code.

bool IsPositive(int number)
{
    if (number > 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

Les instructions en C # contiennent souvent des expressions. Une expression en C # est un fragment de code contenant une valeur littérale, un nom simple ou un opérateur et ses opérandes.

Expression ,

Une expression est un fragment de code qui peut être évalué en une valeur, un objet, une méthode ou un espace de noms unique. Les deux types d'expressions les plus simples sont les littéraux et les noms simples. Un littéral est une valeur constante qui n'a pas de nom.

int i = 5;
string s = "Hello World";

I et s sont des noms simples identifiant des variables locales. Lorsque ces variables sont utilisées dans une expression, la valeur de la variable est récupérée et utilisée pour l'expression.


Je préfère écrire if(number >= 0) return true; else return false;ou encore mieux bool? IsPositive(int number) { if(number > 0) return true; else if(number < 0) return false; else return null;}:)
Mahdi Tahsildari

1

Je préfère le sens de statementdans le sens logique formel du mot. Il en est une qui change l'état d'une ou plusieurs des variables dans le calcul, permettant de faire une déclaration vraie ou fausse sur leur (s) valeur (s).

Je suppose qu'il y aura toujours de la confusion dans le monde de l'informatique et de la science en général lorsque de la nouvelle terminologie ou de nouveaux mots sont introduits, des mots existants sont «réaffectés» ou que les utilisateurs ignorent la terminologie existante, établie ou «appropriée» pour ce qu'ils décrivent.


1

Je ne suis vraiment satisfait d'aucune des réponses ici. J'ai regardé la grammaire du C ++ (ISO 2008) . Cependant, peut-être pour des raisons de didactique et de programmation, les réponses pourraient suffire à distinguer les deux éléments (la réalité semble cependant plus compliquée).

Une instruction se compose de zéro ou plusieurs expressions, mais peut également être d'autres concepts de langage. Il s'agit du formulaire Extended Backus Naur pour la grammaire (extrait de la déclaration):

statement:
        labeled-statement
        expression-statement <-- can be zero or more expressions
        compound-statement
        selection-statement
        iteration-statement
        jump-statement
        declaration-statement
        try-block

Nous pouvons voir les autres concepts qui sont considérés comme des instructions en C ++.

  • expression-instruction s s'explique d'elle-même (une instruction peut comprendre zéro ou plusieurs expressions, lisez attentivement la grammaire, c'est délicat)
  • casepar exemple, est une déclaration étiquetée
  • les instructions de sélection sont if if/else,case
  • -déclaration d'itération s sont while, do...while,for (...)
  • jump-déclaration s sont break, continue, return(peut retourner l' expression),goto
  • déclaration-déclaration est l'ensemble des déclarations
  • try-block est une instruction représentant des try/catchblocs
  • et il pourrait y avoir un peu plus dans la grammaire

Ceci est un extrait montrant la partie des expressions:

expression:
        assignment-expression
        expression "," assignment-expression
assignment-expression:
        conditional-expression
        logical-or-expression assignment-operator initializer-clause
        throw-expression
  • les expressions sont ou contiennent souvent des affectations
  • conditionnelle expression (sons trompeur) fait référence à l' utilisation des opérateurs ( +, -, *, /, &, |, &&, ||, ...)
  • jeter-expression - euh? la throwclause est aussi une expression

0

Les déclarations sont des phrases grammaticalement complètes. Les expressions ne le sont pas. Par exemple

x = 5

se lit comme "x obtient 5." Ceci est une phrase complète. Le code

(x + 5)/9.0

lit, "x plus 5 tous divisés par 9,0." Ce n'est pas une phrase complète. La déclaration

while k < 10: 
    print k
    k += 1

est une phrase complète. Notez que l'en-tête de boucle ne l'est pas; "tandis que k <10," est une clause subordonnée.


whileest une expression est quelques langues telles que Scala. Vous confondez la grammaire avec la dactylographie. Voir ma réponse .
Shelby Moore III

Voici la boucle while dans scala: tutorialspoint.com/scala/scala_ while_loop.htm La boucle avec son prédicat et aucun corps n'est pas une phrase grammaticalement complète. Ce n'est pas une expression complète. Vous avez besoin du corps pour le compléter comme une expression.
ncmathsadist

Un whileavec un corps est toujours une expression en Scala. Il peut également s'agir d'une déclaration si elle crée des effets secondaires, ce que permet ma réponse fortement défavorisée (une expression peut également être une déclaration). Ma réponse est la seule correcte. Désolé à tous ces lecteurs qui ne comprennent pas.
Shelby Moore III

Qu'entendez-vous par grammaticalement complet? En C, (x + 5)/9.0peut certainement être autonome en tant que déclaration. En outre, si par grammaticalement complet, vous entendez un programme valide, C ne permet pas aux instructions de se tenir seules en tant que programme unique.
Akangka

Grammatique complète: constitue une phrase complète.
ncmathsadist

0

Voici le résumé d'une des réponses les plus simples que j'ai trouvées.

Répondu à l'origine par Anders Kaseorg

Une instruction est une ligne complète de code qui effectue une action, tandis qu'une expression est une section du code qui évalue une valeur.

Les expressions peuvent être combinées «horizontalement» en expressions plus grandes à l'aide d'opérateurs, tandis que les instructions ne peuvent être combinées «verticalement» qu'en écrivant les unes après les autres, ou avec des constructions de blocs.

Chaque expression peut être utilisée comme une instruction (dont l'effet est d'évaluer l'expression et d'ignorer la valeur résultante), mais la plupart des instructions ne peuvent pas être utilisées comme expressions.

http://www.quora.com/Python-programming-language-1/Whats-the-difference-between-a-statement-and-an-expression-in-Python


0

La base de facto de ces concepts est:

Expressions : catégorie syntaxique dont l'instance peut être évaluée en une valeur.

Instruction : une catégorie syntaxique dont l'instance peut être impliquée dans les évaluations d'une expression et la valeur résultante de l'évaluation (le cas échéant) n'est pas garantie disponible.

Outre le contexte très initial de FORTRAN dans les premières décennies, les définitions des expressions et des déclarations dans la réponse acceptée sont évidemment fausses:

  • Les expressions peuvent être des opérandes non évalués. Des valeurs n'en sont jamais produites.
    • Les sous-expressions dans les évaluations non strictes peuvent être définitivement non évaluées.
      • La plupart des langages de type C ont les règles dites d' évaluation de court-circuit pour sauter conditionnellement certaines évaluations de sous-expression et ne pas changer le résultat final malgré les effets secondaires.
    • C et certains langages de type C ont la notion d'opérande non évalué qui peut même être normativement défini dans la spécification du langage. De telles constructions sont utilisées pour éviter définitivement les évaluations, de sorte que les informations de contexte restantes (par exemple, les types ou les exigences d'alignement) peuvent être distinguées statiquement sans changer le comportement après la traduction du programme.
      • Par exemple, une expression utilisée comme opérande de l' sizeofopérateur n'est jamais évaluée.
  • Les instructions n'ont rien à voir avec les constructions de lignes. Ils peuvent faire autre chose que des expressions, selon les spécifications du langage.
    • Le Fortran moderne, en tant que descendant direct de l'ancien FORTRAN, a des concepts d' instructions exécutables et d' instructions non exécutables .
    • De même, C ++ définit les déclarations comme la sous-catégorie de niveau supérieur d'une unité de traduction. Une déclaration en C ++ est une instruction. (Ce n'est pas vrai en C.) Il existe également des instructions d'expression comme les instructions exécutables de Fortran.
    • Dans l'intérêt de la comparaison avec les expressions, seules les instructions "exécutables" importent. Mais vous ne pouvez pas ignorer le fait que les déclarations sont déjà généralisées pour être des constructions formant les unités de traduction dans de telles langues impératives. Donc, comme vous pouvez le voir, les définitions de la catégorie varient beaucoup. La propriété (probablement) restée commune et préservée parmi ces langues est que les déclarations devraient être interprétées dans l'ordre lexical (pour la plupart des utilisateurs, de gauche à droite et de haut en bas).

(BTW, je veux ajouter [la citation nécessaire] à cette réponse concernant les documents sur C parce que je ne me souviens pas si DMR a de telles opinions. Il ne semble pas, sinon il ne devrait pas y avoir de raisons de préserver la duplication des fonctionnalités dans la conception de C : notamment, l'opérateur virgule vs les instructions.)

(La justification suivante n'est pas la réponse directe à la question d'origine, mais je pense qu'il est nécessaire de clarifier quelque chose qui a déjà répondu ici.)

Néanmoins, il est douteux que nous ayons besoin d'une catégorie spécifique d '"instructions" dans les langages de programmation à usage général:

  • Les instructions ne sont pas garanties d'avoir plus de capacités sémantiques sur les expressions dans les conceptions habituelles.
    • De nombreuses langues ont déjà abandonné avec succès la notion de déclarations pour obtenir des conceptions globales propres, soignées et cohérentes.
      • Dans de tels langages, les expressions peuvent faire tout ce que les instructions à l'ancienne peuvent faire: il suffit de supprimer les résultats inutilisés lorsque les expressions sont évaluées, soit en laissant les résultats explicitement non spécifiés (par exemple dans le schéma R n RS), soit en ayant une valeur spéciale (en tant que valeur d'un type d'unité) non réalisable à partir d'évaluations d'expressions normales.
      • Les règles d'ordre lexical d'évaluation des expressions peuvent être remplacées par un opérateur de contrôle de séquence explicite (par exemple begindans Scheme) ou du sucre syntaxique de structures monadiques.
      • Les règles d'ordre lexical d'autres types d '"instructions" peuvent être dérivées sous forme d'extensions syntaxiques (en utilisant des macros hygiéniques, par exemple) pour obtenir la fonctionnalité syntaxique similaire. (Et cela peut en fait faire plus .)
    • Au contraire, les déclarations ne peuvent pas avoir de telles règles conventionnelles, car elles ne font pas partie de l'évaluation: il n'y a tout simplement pas une telle notion commune d '"évaluation de sous-déclaration". (Même s'il y en a, je doute qu'il puisse y avoir bien plus que du copier-coller à partir des règles existantes d'évaluation des expressions.)
      • En règle générale, les langages préservant les instructions auront également des expressions pour exprimer les calculs, et il existe une sous-catégorie de niveau supérieur des instructions préservées pour les évaluations d'expressions pour cette sous-catégorie. Par exemple, C ++ a la soi-disant expression-instruction comme sous-catégorie et utilise les règles d'évaluation d' expression de valeur rejetée pour spécifier les cas généraux des évaluations d'expression complète dans un tel contexte. Certains langages comme C # choisissent d'affiner les contextes pour simplifier les cas d'utilisation, mais il alourdit davantage la spécification.
  • Pour les utilisateurs de langages de programmation, la signification des instructions peut les confondre davantage.
    • La séparation des règles d'expressions et des énoncés dans les langues nécessite plus d'efforts pour apprendre une langue.
    • L'interprétation naïve de l'ordre lexical cache la notion la plus importante: l'évaluation de l'expression. (C'est probablement le plus problématique dans l'ensemble.)
      • Même les évaluations d'expressions complètes dans les instructions sont contraintes avec l'ordre lexical, les sous-expressions ne le sont pas (nécessairement). Les utilisateurs devraient en fin de compte apprendre cela en plus des règles associées aux déclarations. (Réfléchissez à comment faire pour qu'un débutant obtienne le point qui ++i + ++in'a pas de sens en C.)
      • Certains langages comme Java et C # contraignent davantage l'ordre d'évaluation des sous-expressions à permettre l'ignorance des règles d'évaluation. Cela peut être encore plus problématique.
        • Cela semble sur-spécifié aux utilisateurs qui ont déjà appris l'idée de l'évaluation de l'expression. Il encourage également la communauté des utilisateurs à suivre le modèle mental flou de la conception du langage.
        • Cela gonfle encore plus la spécification de la langue.
        • Elle nuit à l'optimisation en manquant l'expressivité du non-déterminisme sur les évaluations, avant l'introduction de primitives plus compliquées.
      • Quelques langages comme C ++ (en particulier, C ++ 17) spécifient des contextes plus subtils de règles d'évaluation, comme un compromis des problèmes ci-dessus.
        • Cela gonfle beaucoup les spécifications linguistiques.
        • Cela va totalement à l'encontre de la simplicité pour les utilisateurs moyens ...

Alors pourquoi des déclarations? Quoi qu'il en soit, l'histoire est déjà un gâchis. Il semble que la plupart des concepteurs de langues ne prennent pas leur choix avec soin.

Pire encore, cela donne même à certains amateurs de systèmes de types (qui ne connaissent pas suffisamment l'histoire du PL) des idées fausses selon lesquelles les systèmes de types doivent avoir des choses importantes à faire avec les conceptions plus essentielles des règles sur la sémantique opérationnelle.

Sérieusement, le raisonnement selon les types n'est pas si mal dans de nombreux cas, mais surtout pas constructif dans ce cas particulier. Même les experts peuvent tout gâcher.

Par exemple, quelqu'un met l'accent sur la nature bien typée comme argument central contre le traitement traditionnel des continuations non délimitées . Bien que la conclusion soit quelque peu raisonnable et que les informations sur les fonctions composées soient correctes ( mais encore beaucoup trop naïves à l'essentiel ), cet argument n'est pas valable car il ignore totalement l'approche "canal latéral" dans la pratique comme _Noreturn any_of_returnable_types(en C11) pour coder Falsum. Et à proprement parler, une machine abstraite à l'état imprévisible n'est pas identique à "un ordinateur en panne".


0

Dans un langage de programmation orienté instructions, un bloc de code est défini comme une liste d'instructions. En d'autres termes, une instruction est un élément de syntaxe que vous pouvez placer dans un bloc de code sans provoquer d'erreur de syntaxe.

Wikipédia définit le mot énoncé de la même façon

En programmation informatique, un énoncé est une unité syntaxique d'un langage de programmation impératif qui exprime une action à effectuer. Un programme écrit dans un tel langage est formé par une séquence d'une ou plusieurs instructions

Notez la dernière déclaration. (bien que "un programme" dans ce cas soit techniquement incorrect parce que C et Java rejettent un programme qui ne contient rien d'instructions.)

Wikipedia définit l'expression du mot comme

Une expression dans un langage de programmation est une entité syntaxique qui peut être évaluée pour déterminer sa valeur

Ceci est cependant faux, car dans Kotlin, throw new Exception("")est une expression mais lorsqu'elle est évaluée, elle lève simplement une exception, ne renvoyant jamais aucune valeur.

Dans un langage de programmation typé statiquement, chaque expression a un type. Cette définition, cependant, ne fonctionne pas dans un langage de programmation typé dynamiquement.

Personnellement, je définis une expression comme un morceau de syntaxe qui peut être composé avec un opérateur ou des appels de fonction pour produire une expression plus grande. Ceci est en fait similaire à l'explication de l'expression par Wikipedia:

C'est une combinaison d'une ou plusieurs constantes, variables, fonctions et opérateurs que le langage de programmation interprète (selon ses règles de précédence et d'association particulières) et calcule pour produire ("retourner", dans un environnement avec état) une autre valeur

Mais, le problème est dans le langage de programmation C, étant donné une fonction executeSomething comme ceci:

void executeSomething(void){
    return;
}

Est-ce executeSomething()une expression ou une déclaration? Selon ma définition, il s'agit d'une déclaration car, comme défini dans la grammaire de référence C de Microsoft,

Vous ne pouvez pas utiliser la valeur (inexistante) d'une expression qui a le type void de quelque façon que ce soit, ni convertir une expression void (par conversion implicite ou explicite) en n'importe quel type sauf void

Mais la même page indique clairement qu'une telle syntaxe est une expression.


-6

Pour améliorer et valider ma réponse précédente, les définitions des termes du langage de programmation doivent être expliquées à partir de la théorie des types informatiques, le cas échéant.

Une expression a un type autre que le type Bottom, c'est-à-dire qu'elle a une valeur. Une instruction a le type Unit ou Bottom.

Il s'ensuit qu'une instruction ne peut avoir d'effet dans un programme que lorsqu'elle crée un effet secondaire, car elle ne peut pas renvoyer de valeur ou elle ne renvoie que la valeur du type Unit qui est soit non assignable (dans certaines langues telles que un C void) ou (comme dans Scala) peuvent être stockés pour une évaluation différée de la déclaration.

De toute évidence, a @pragmaou a /*comment*/n'ont pas de type et sont donc différenciés des déclarations. Ainsi, le seul type de déclaration qui n'aurait aucun effet secondaire serait une non-opération. La non-opération n'est utile que comme espace réservé pour de futurs effets secondaires. Toute autre action due à une déclaration serait un effet secondaire. Encore une fois, un indice du compilateur, par exemple @pragma, n'est pas une instruction car il n'a pas de type.


2
La distinction n'a rien à voir avec le type d'expressions. Les instructions définies syntaxiquement n'ont aucun type dans de nombreuses langues. Bien que je ne sois pas contre pour attribuer un type à de tels termes en théorie, différents traitements sur @pragmaou /*comment*/sont logiquement incohérents.
FrankHB

-11

Plus précisément, une déclaration doit avoir un «effet secondaire» (c'est- à- dire être impérative ) et une expression doit avoir un type de valeur (c'est-à-dire pas le type inférieur).

Le type d'une déclaration est le type d'unité, mais en raison de l'unité du théorème de Halting, c'est de la fiction, alors disons le type du bas .


Voidn'est pas précisément le type inférieur (ce n'est pas le sous-type de tous les types possibles). Il existe dans des langues qui n'ont pas de système de type complètement sonore . Cela peut ressembler à une déclaration snob, mais l'exhaustivité comme les annotations de variance est essentielle à l'écriture d'un logiciel extensible.

Voyons ce que Wikipedia a à dire à ce sujet.

https://en.wikipedia.org/wiki/Statement_(computer_science)

En programmation informatique, une déclaration est le plus petit élément autonome d'un langage de programmation impératif qui exprime une action à effectuer.

De nombreux langages (par exemple C) font une distinction entre les instructions et les définitions, une instruction ne contenant que du code exécutable et une définition déclarant un identifiant, tandis qu'une expression ne prend en compte qu'une valeur.


5
Une déclaration n'a pas besoin d'avoir un effet secondaire. Par exemple, en python passest une déclaration. C'est un no-op, et il n'évalue rien.
Matthew Schinckel

9
-1 C'est faux. Une déclaration n'a pas avoir d'avoir un effet secondaire. Voir la section 1.5 de la spécification du langage C # . Non seulement il ne spécifie pas que les instructions doivent avoir des effets secondaires, mais il répertorie également plusieurs instructions qui ne peuvent pas avoir d' effets secondaires.
NullUserException

2
@NullUserException J'ai lu cette section. Les instructions Declaration, Expression, Selection, Iteration et Jump peuvent toutes créer des effets secondaires. Mais s'il y a une expression RT, ce n'est pas une déclaration. Je me rends compte que la spécification assimile les expressions aux déclarations, mais cette question a demandé la différence entre elles. Donc, soit la question n'a pas de réponse, soit vous prenez la spécification C # trop littéralement. La réponse la plus votée essaie de dire ce que j'ai fait. Mais "fait quelque chose" n'a pas de sens. «effet secondaire» est la façon significative de dire «fait quelque chose». Nous devons penser, pas seulement régurgiter.
Shelby Moore III

13
@ShelbyMooreIII Vous avez raison. La documentation officielle est fausse . Marc Gravell et Jon Skeet, qui sont probablement les affiches C # les plus respectueuses actives sur SO en dehors d'Eric Lippert, ont tort . Moi, et tous les autres qui vous ont voté et laissé des commentaires expliquant notre position sont faux . Tu as raison. Vous êtes clairement la seule personne qui sait de quoi ils parlent, car vous êtes tellement plus intelligent que tout le reste de SO.
NullUserException

3
Connaître la définition précise de concepts tels que déclaration, expression, distribution, conversion, etc. n'a aucun impact sur 99,999% des tâches de programmation quotidiennes. Pensez -y . Aussi: la plupart des gens ne se soucient pas de Haskell et Scala.
NullUserException
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.