458

c# について質問していますが、他のほとんどの言語でも同じだと思います。

ステートメントの適切な定義と、その違いを知っている人はいますか?

4

21 に答える 21

552

式:値に評価されるもの。例: 1+2/x
ステートメント:何かを実行するコード行。例: GOTO 100

FORTRAN などの初期の汎用プログラミング言語では、この区別は非常に明確でした。FORTRAN では、ステートメントは実行の 1 つの単位であり、ユーザーが行うことでした。「行」と呼ばれなかった唯一の理由は、複数の行にまたがることがあるためです。式だけでは何もできません...変数に代入する必要がありました。

1 + 2 / X

何もしないので、FORTRAN ではエラーです。あなたはその式で何かをしなければなりませんでした:

X = 1 + 2 / X

FORTRAN には、今日知られているような文法はありませんでした。この考えは、Algol-60 の定義の一部として、Backus-Naur Form (BNF) とともに発明されました。その時点で、セマンティックの区別 (「値を持つ」と「何かを行う」) が構文に組み込まれていました。ある種類のフレーズは式であり、別の種類のフレーズはステートメントであり、パーサーはそれらを区別できました。

後の言語の設計者は、この区別をあいまいにしました。つまり、構文式で何かを行うことを許可し、値を持つ構文ステートメントを許可しました。まだ生き残っている最も初期の一般的な言語の例は C です。C の設計者は、式を評価して結果を破棄しても問題はないと認識していました。C では、最後にセミコロンを追加するだけで、すべての構文式をステートメントにすることができます。

1 + 2 / x;

絶対に何も起こらないにもかかわらず、完全に合法的な声明です。同様に、C では、式に副作用があり、何かを変更する可能性があります。

1 + 2 / callfunc(12);

callfunc何か役に立つことをするかもしれないからです。

任意の式をステートメントにすることを許可したら、式内で代入演算子 (=) を許可することもできます。そのため、C では次のようなことができます。

callfunc(x = 2);

これは式 x = 2 を評価し (2 の値を x に代入)、それ (2) を function に渡しますcallfunc

式とステートメントのこの曖昧さは、すべての C 派生物 (C、C++、C#、および Java) で発生します。これらにはまだいくつかのステートメント ( などwhile) がありますが、ほとんどすべての式をステートメントとして使用できます (C# のみの代入では、 call、increment、decrement 式をステートメントとして使用できます ( Scott Wisniewski の回答を参照)。

2 つの「構文カテゴリ」(ステートメントと式の種類の技術的な名前) があると、作業が重複する可能性があります。たとえば、C には 2 つの形式の条件文があります。

if (E) S1; else S2;

そして表現形式

E ? E1 : E2

また、存在しない重複が必要な場合もあります。たとえば、標準 C では、新しいローカル変数を宣言できるのはステートメントのみです。しかし、この機能は十分に有用であり、GNU C コンパイラーは、式でローカル変数を宣言できるようにする GNU 拡張機能を提供しています。ローカル変数も。

他の言語の設計者は、この種の重複を好まず、式が値だけでなく副作用も持つ可能性がある場合、ステートメントと式の間の構文上の区別はあまり役に立たないことに早い段階で気付きました。 . Haskell、Icon、Lisp、および ML はすべて、構文ステートメントを持たない言語です。これらには式しかありません。クラス構造のループや条件付きフォームも式と見なされ、値を持ちますが、あまり興味深いものではありません。

于 2008-08-21T02:17:21.000 に答える
24
  • 式は、値を生成するものです:2 + 2
  • ステートメントは、プログラム実行の基本的な「ブロック」の1つです。

Cでは、「=」は実際には演算子であり、次の2つのことを行うことに注意してください。

  • 右側の部分式の値を返します。
  • 右側の部分式の値を左側の変数にコピーします。

これは、ANSIC文法からの抜粋です。Cには多くの異なる種類のステートメントがないことがわかります...プログラム内のステートメントの大部分は式ステートメントです。つまり、末尾にセミコロンが付いた式です。

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

于 2008-08-21T05:05:58.893 に答える
16

式は値を返すものですが、ステートメントは値を返しません。

例えば:

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

この 2 つの大きな違いは、ステートメントを連鎖できないのに対し、式を連鎖できることです。

于 2008-08-21T00:30:44.093 に答える
11

これはwikipediaで見つけることができますが、ステートメントには評価値がありませんが、式は何らかの値に評価されます。

したがって、ステートメントで式を使用することはできますが、その逆はできません。

一部の言語 (Lisp など、Ruby や他の多くの言語) はステートメントと式を区別しないことに注意してください。そのような言語では、すべてが式であり、他の式と連鎖させることができます。

于 2008-08-21T00:35:13.227 に答える
8

式とステートメントの構成可能性 (チェーン可能性) の重要な違いの説明については、ジョン・バッカスのチューリング賞の論文、フォン・ノイマン スタイルからプログラミングを解放できますか?が私のお気に入りの参考文献です。.

命令型言語 (Fortran、C、Java など) は、プログラムを構造化するためのステートメントを重視し、一種の後付けとして式を持ちます。関数型言語は式を強調します。 純粋関数型言語には、ステートメントを完全に削除できるほど強力な式があります。

于 2009-06-23T20:49:57.917 に答える
7

式は値を取得するために評価できますが、ステートメントは値を返しません (型はvoidです)。

もちろん、関数呼び出し式もステートメントと見なすことができますが、実行環境に戻り値を保持するための特別な組み込み変数がない限り、それを取得する方法はありません。

ステートメント指向言語では、すべての手続きがステートメントのリストである必要があります。おそらくすべて関数型言語である式指向言語は、式のリスト、または LISP の場合、式のリストを表す 1 つの長い S 式です。

両方の型を構成できますが、型が一致する限り、ほとんどの式を任意に構成できます。ステートメントの各タイプには、他のステートメントを構成する独自の方法があります。foreach および if ステートメントは、サブステートメントが独自のサブステートメントを許可しない限り、単一のステートメントを必要とするか、すべての従属ステートメントをステートメント ブロックに次々と入れる必要があります。

ステートメントには式を含めることもできますが、式には実際にはステートメントが含まれていません。ただし、1 つの例外は、関数を表すラムダ式であり、言語が Python の単一式ラムダのように限定されたラムダのみを許可しない限り、関数に含めることができるものはすべて含めることができます。

式ベースの言語では、すべての制御構造が値を返す (多くは NIL を返す) ため、必要なのは関数の単一の式だけです。関数内で最後に評価された式が戻り値であるため、return ステートメントは必要ありません。

于 2008-08-21T00:30:31.957 に答える
5

簡単に言うと、式は値に評価されますが、ステートメントは評価されません。

于 2008-08-21T00:31:55.620 に答える
4

式ベースの言語に関するいくつかのこと:


最も重要: すべてが値を返す


すべてが式であるため、コード ブロックと式を区切るための中括弧と中括弧に違いはありません。ただし、これはレキシカルスコープを妨げません。たとえば、ローカル変数は、その定義が含まれる式とその中に含まれるすべてのステートメントに対して定義できます。


式ベースの言語では、すべてが値を返します。これは最初は少し奇妙かもしれません -- 何を(FOR i = 1 TO 10 DO (print i))返しますか?

簡単な例:

  • (1)戻り値1
  • (1 + 1)戻り値2
  • (1 == 1)戻り値TRUE
  • (1 == 2)戻り値FALSE
  • (IF 1 == 1 THEN 10 ELSE 5)戻り値10
  • (IF 1 == 2 THEN 10 ELSE 5)戻り値5

いくつかのより複雑な例:

  • 一部の関数呼び出しなど、実際には意味のある値を返さないものもあります (副作用しか生じないもの?)。OpenADoor(), FlushTheToilet()orを呼び出す TwiddleYourThumbs()と、OK、Done、Success などのありふれた値が返されます。
  • 複数のリンクされていない式が 1 つの大きな式内で評価される場合、大きな式で最後に評価されたものの値が大きな式の値になります。の例を挙げると(FOR i = 1 TO 10 DO (print i))、for ループの値は「10」です。これにより、(print i)式が 10 回評価され、そのたびに i が文字列として返されます。最終回の返品10、弊社の最終回答

すべてが式であるという事実により、多くのものを「インライン化」できるため、式ベースの言語を最大限に活用するには、わずかな考え方の変更が必要になることがよくあります。

簡単な例として:

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

非式ベースの完全に有効な代替品です

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

場合によっては、式ベースのコードで許可されるレイアウトの方が、私にははるかに自然に感じられます。

もちろん、これは狂気につながる可能性があります。MaxScript と呼ばれるエクスプレッション ベースのスクリプト言語を使用した趣味のプロジェクトの一環として、私はこのモンスター ラインを思いつくことができました。

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
)
于 2008-12-19T01:36:29.443 に答える
2

ステートメントは、式の特殊なケースであり、voidタイプがあります。言語がステートメントを異なる方法で扱う傾向があると、問題が発生することがよくあります。適切に一般化されているとよいでしょう。

たとえば、C#には、非常に便利なFunc<T1, T2, T3, TResult>オーバーロードされたジェネリックデリゲートのセットがあります。しかし、対応するAction<T1, T2, T3>セットも必要であり、この不幸な分岐に対処するには、汎用の高次プログラミングを常に複製する必要があります。

簡単な例-別の関数を呼び出す前に、参照がnullかどうかをチェックする関数:

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

TResultコンパイラはその可能性に対処できvoidますか?はい。それがしなければならないのは、returnの後にタイプの式が続くことを要求することだけですvoid。の結果はdefault(void)タイプvoidであり、渡される関数は次の形式である必要がありますFunc<TValue, void>(これはと同等ですAction<TValue>)。

他の多くの答えは、式のようにステートメントを連鎖させることができないことを示唆していますが、このアイデアがどこから来ているのかはわかりません。ステートメントの後に表示されるは、2つの型の式を取り、それらを1つの型の式に結合する;バイナリ中置演算子と考えることができます。voidvoid

于 2009-03-14T17:35:38.943 に答える
2

ステートメント -> 順番に従う命令
式 -> 値を返す評価

ステートメントは基本的にステップ、またはアルゴリズムの命令に似ています。ステートメントの実行の結果は、命令ポインター (いわゆるアセンブラー) の実現化です。

式は一目で実行順序を示すものではなく、その目的は値を評価して返すことです。命令型プログラミング言語では、式の評価に順序がありますが、それは単に命令型モデルのためであり、本質ではありません。

ステートメントの例:

for
goto
return
if

(いずれも実行の行(文)を別の行に進めることを暗示しています)

式の例:

2+2

(実行という意味ではなく、評価という意味です)

于 2012-09-05T15:47:14.983 に答える
1

statement私は、言葉の形式論理的な意味での意味を好みます。これは、計算で 1 つ以上の変数の状態を変更し、それらの値について true または false のステートメントを作成できるようにするものです。

新しい用語や単語が導入されたり、既存の単語が「転用」されたり、ユーザーが説明している既存の確立された用語や「適切な」用語を知らない場合、コンピューティングの世界や科学全般では常に混乱が生じると思います。

于 2013-05-07T15:18:17.943 に答える
1

これは、私が見つけた最も単純な答えの要約です。

Anders Kaseorgによる最初の回答

ステートメントは何らかのアクションを実行する完全なコード行であり、式は値に評価されるコードの任意のセクションです。

式は、演算子を使用して「水平方向」に結合してより大きな式にすることができますが、ステートメントは、次々に記述するか、ブロック構造を使用して「垂直方向」に結合することしかできません。

すべての式はステートメントとして使用できます (その効果は、式を評価し、結果の値を無視することです) が、ほとんどのステートメントは式として使用できません。

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

于 2014-09-08T10:46:07.230 に答える
1

ステートメント,

ステートメントは、すべての C# プログラムの構築元となる手続き型のビルディング ブロックです。ステートメントでは、ローカル変数または定数を宣言したり、メソッドを呼び出したり、オブジェクトを作成したり、変数、プロパティ、またはフィールドに値を割り当てたりできます。

中かっこで囲まれた一連のステートメントは、コードのブロックを形成します。メソッド本体は、コード ブロックの一例です。

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

C# のステートメントには、多くの場合、式が含まれています。C# の式は、リテラル値、単純な名前、または演算子とそのオペランドを含むコードのフラグメントです。

式は、単一の値、オブジェクト、メソッド、または名前空間に評価できるコードの断片です。最も単純な 2 つのタイプの式は、リテラルと単純な名前です。リテラルは、名前のない定数値です。

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

i と s はどちらもローカル変数を識別する単純な名前です。これらの変数が式で使用されると、変数の値が取得され、式に使用されます。

于 2012-09-17T12:11:07.157 に答える
1

これらの概念の事実上の基礎は次のとおりです。

Expressions : インスタンスを値に評価できる構文カテゴリ。

Statement : インスタンスが式の評価に関与する可能性があり、評価の結果の値 (存在する場合) が利用可能であることが保証されていない構文カテゴリ。

初期の数十年のFORTRANの非常に初期のコンテキストに加えて、受け入れられた回答の式とステートメントの両方の定義は明らかに間違っています:

  • 式は未評価のオペランドにすることができます。それらから値が生成されることはありません。
    • 非正格評価の部分式は、間違いなく未評価になる可能性があります。
      • ほとんどの C ライクな言語には、副作用があっても最終結果を変更しない部分式の評価を条件付きでスキップする、いわゆる短絡評価規則があります。
    • C および一部の C に似た言語には、言語仕様で規範的に定義されている可能性のある未評価のオペランドの概念があります。このような構造は、評価を確実に回避するために使用されるため、プログラムの翻訳後に動作を変更することなく、残りのコンテキスト情報 (型やアラインメント要件など) を静的に区別できます。
      • たとえば、sizeof演算子のオペランドとして使用される式は評価されません。
  • ステートメントは行構造とは何の関係もありません。言語仕様によっては、式以外のこともできます。
    • 古い FORTRAN の直系の子孫である最新の Fortran には、実行可能ステートメントと非実行可能ステートメントの概念あります。
    • 同様に、C++ は宣言を翻訳単位の最上位サブカテゴリとして定義します。C++ の宣言はステートメントです。(これは C では当てはまりません。) Fortran の実行可能ステートメントのような式ステートメントもあります。
    • 式との比較では、「実行可能な」ステートメントのみが重要です。しかし、そのような命令型言語では、ステートメントが既に一般化されて翻訳単位を形成する構造になっているという事実を無視することはできません。ご覧のとおり、カテゴリの定義は大きく異なります。これらの言語間で保存されている (おそらく) 唯一の共通のプロパティは、ステートメントが語彙の順序(ほとんどのユーザーにとって、左から右、上から下)で解釈されることが期待されるということです。

(ところで、DMRがそのような意見を持っているかどうか思い出せないので、Cに関する資料に関するその回答に[引用が必要です]を追加したいと思います。そうではないようです。そうでなければ、Cの設計で機能の重複を維持する理由はないはずです: 特に、コンマ演算子とステートメントの比較です。)

(次の論理的根拠は、元の質問に対する直接の回答ではありませんが、ここで既に回答されていることを明確にする必要があると感じています。)

それにもかかわらず、汎用プログラミング言語で特定のカテゴリの「ステートメント」が必要かどうかは疑わしいです。

  • 通常の設計では、ステートメントが式よりもセマンティックな機能を備えているとは限りません。
    • 多くの言語は、ステートメントの概念を放棄することに成功し、クリーンで整然とした一貫した全体的なデザインを実現しています。
      • そのような言語では、式は古いスタイルのステートメントでできるすべてのことを行うことができます: 式が評価されるときに未使用の結果を削除するだけです。結果を明示的に未指定のままにしておくか (R n RS スキームなど)、特別な値を (ユニット型の値) は、通常の式の評価から生成できません。
      • 式の評価の字句順序規則は、明示的なシーケンス制御演算子 ( beginScheme など) またはモナド構造の構文糖衣に置き換えることができます。
      • 他の種類の「ステートメント」の字句順序規則は、同様の構文機能を得るために、構文拡張 (たとえば、ハイジェニック マクロを使用) として導出できます。(そして、実際にはもっと多くのことができます。)
    • それどころか、ステートメントは評価で構成しないため、そのような従来のルールを持つことはできません。「サブステートメント評価」のような一般的な概念はありません。(あったとしても、式の評価に関する既存の規則からのコピー アンド ペースト以上のものがあるとは思えません。)
      • 通常、ステートメントを保持する言語には計算を表現する式もあり、そのサブカテゴリの式評価に保持されるステートメントのトップレベルのサブカテゴリがあります。たとえば、C++ にはサブカテゴリとしていわゆる式ステートメントがあり、破棄値式評価規則を使用して、そのようなコンテキストでの完全式評価の一般的なケースを指定します。C# などの一部の言語は、ユース ケースを単純化するためにコンテキストを改良することを選択しますが、仕様をさらに肥大化させます。
  • プログラミング言語のユーザーにとっては、ステートメントの意味がさらに混乱を招く可能性があります。
    • 言語の表現とステートメントのルールを分離すると、言語を習得するためにより多くの努力が必要になります。
    • 単純な字句順序の解釈では、より重要な概念である式の評価が隠されています。(これはおそらく、すべての中で最も問題があります。)
      • ステートメント内の完全な式の評価でさえ、字句順序による制約がありますが、部分式はそうではありません (必然的に)。ユーザーは、ステートメントに結合されたルールに加えて、最終的にこれを学ぶ必要があります。++i + ++i(初心者に C では無意味な点を理解させる方法を考えてください。)
      • Java や C# などの一部の言語では、部分式の評価の順序をさらに制限して、評価規則を無視することを許容しています。さらに問題になる可能性があります。
        • これは、式の評価の考え方をすでに学んでいるユーザーには過剰に指定されているように見えます。また、ユーザー コミュニティが言語設計のぼやけたメンタル モデルに従うように促します。
        • 言語仕様をさらに肥大化させます。
        • より複雑なプリミティブが導入される前に、評価の非決定性の表現力を失うことにより、最適化に有害です。
      • C++ (特に C++17) のようないくつかの言語は、上記の問題の妥協点として、評価規則のより微妙なコンテキストを指定します。
        • 言語仕様を大幅に肥大化させます。
        • これは、平均的なユーザーへのシンプルさに完全に反します...

では、なぜ声明を出すのでしょうか。とにかく、歴史はすでにめちゃくちゃです。ほとんどの言語設計者は慎重に選択していないようです。

さらに悪いことに、一部の型システム愛好家 (PL の歴史に十分に精通していない) に、型システムは操作セマンティクスに関するより本質的な規則の設計に関係する重要な事柄を持たなければならないという誤解を与えることさえあります。

真剣に、タイプに依存する推論は多くの場合それほど悪くはありませんが、この特別なものでは特に建設的ではありません. 専門家でさえ、物事を台無しにすることができます。

たとえば、誰かが、区切りのない継続の伝統的な扱いに対する中心的な議論として、適切な型付けの性質を強調しています。結論はいくぶん合理的であり、構成された関数についての洞察は問題ありませんが (ただし、本質的にはあまりにも単純すぎます_Noreturn any_of_returnable_types)、この議論は適切ではありません。これは、実際には(C11 で) エンコードするなどの「サイド チャネル」アプローチを完全に無視しているためFalsumです。 そして厳密に言えば、予測不可能な状態の抽象的なマシンは、「クラッシュしたコンピューター」と同じではありません。

于 2019-08-23T03:50:07.840 に答える
0

Statements are grammatically complete sentences. Expressions are not. For example

x = 5

reads as "x gets 5." This is a complete sentence. The code

(x + 5)/9.0

reads, "x plus 5 all divided by 9.0." This is not a complete sentence. The statement

while k < 10: 
    print k
    k += 1

is a complete sentence. Notice that the loop header is not; "while k < 10," is a subordinating clause.

于 2011-03-26T01:40:12.077 に答える
-7

私の以前の回答を改善して検証するには、プログラミング言語の用語の定義は、該当する場合はコンピュータ サイエンスの型理論から説明する必要があります。

式に Bottom タイプ以外のタイプがあります。つまり、値があります。ステートメントには、Unit または Bottom タイプがあります。

このことから、ステートメントは、値を返すことができないか、代入不可能な Unit 型の値のみを返すため、副作用を作成するときにのみプログラム内で効果を持つことができます (一部の言語では、 C のvoid) または (Scala の場合など) は、ステートメントの遅延評価のために格納できます。

明らかに a@pragmaまたは a/*comment*/には型がないため、ステートメントとは区別されます。したがって、副作用のないステートメントの唯一のタイプは、非操作です。非操作は、将来の副作用のプレースホルダーとしてのみ役立ちます。ステートメントによるその他のアクションは、副作用になります。ここでも、コンパイラ ヒント (例: @pragma) は型を持たないため、ステートメントではありません。

于 2015-08-17T18:25:20.783 に答える
-12

最も正確には、ステートメントには「副作用」が必要であり(つまり、命令型である必要あります)、式にはの型が必要です (つまり、下位の型ではない)。

の型は単位型ですが、ホールティング定理により単位はフィクションなので底型としましょう。


Void正確には最下位の型ではありません (考えられるすべての型のサブタイプではありません)。完全な型システムを持たない言語に存在します。それは卑劣な発言のように聞こえるかもしれませんが、バリアンス アノテーションなどの完全性は、拡張可能なソフトウェアを作成するために重要です。

ウィキペディアがこの問題について何と言っているか見てみましょう。

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

コンピューター プログラミングでは、ステートメントは、実行するアクションを表現する命令型プログラミング言語の最小のスタンドアロン要素です。

多くの言語 (C など) では、ステートメントと定義が区別されます。ステートメントには実行可能コードのみが含まれ、定義には識別子が宣言されますが、式は値のみに評価されます。

于 2011-12-09T19:04:39.753 に答える