式とステートメント


431

私はc#について尋ねていますが、他のほとんどの言語でも同じだと思います。

誰かが表現ステートメントの良い定義を持っていますか、そしてその違いは何ですか?


4
あなたが選んだ答えがあいまいです。式も何かを行います-それは値に評価されます。私は明確な答えを提供しました。
シェルビームーアIII

4
@ShelbyMooreIII-あいまいではなく、間違っている。受け入れられた回答は非公式な方法で表現されますが、その表現によって理解が容易になります。最も重要なのは、それが伝える意味が正確であることです。
Justin Morgan、

@JustinMorgan残念ながら、受け入れられた回答の定義も明らかに間違っています(「値に評価」/「コード行」)。Cに似たものを含むほとんどの現代的な言語:評価されていないコンテキストで式を使用でき、ステートメントに何もありません線で行う。いくつかの説明がありますが、短い答えは混乱を招き、誤解を招きます。
-FrankHB

回答:


520

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

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

1 + 2 / X

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

X = 1 + 2 / X

FORTRANには、私たちが今日知っているような文法はありませんでした。その考えは、Algol-60の定義の一部としてバッカスナウアフォーム(BNF)とともに考案されました。その時点で、セマンティックの違い(「値を持っている」と「何かをする」)が構文に安置されていました。ある種類のフレーズは式であり、別のフレーズはステートメントであり、パーサーはそれらを区別できました。

後の言語の設計者は、区別をあいまいにしました。構文式が物事を行うことを許可し、値を持つ構文ステートメントを許可しました。まだ生き残っている最も初期の人気のある言語の例はCです。Cの設計者は、式を評価して結果を破棄することが許可されていれば害はないことに気付きました。Cでは、末尾にセミコロンを付けるだけで、すべての構文式をステートメントにすることができます。

1 + 2 / x;

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

1 + 2 / callfunc(12);

callfunc何か便利なことがあるからです。

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

callfunc(x = 2);

これは、式x = 2(2の値をxに割り当てる)を評価し、それ(2)を関数に渡しますcallfunc

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

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

if (E) S1; else S2;

そして表現形式

E ? E1 : E2

そして、時には人々が望んがない重複を標準Cには、例えば、唯一のステートメントは、宣言することができ、新たなローカル変数-が、この能力は、GNU Cコンパイラを宣言するために発現を可能にGNUの拡張機能を提供することを便利に十分ですローカル変数も同様です。

他の言語の設計者はこの種の複製を好まなかったため、式に副作用だけでなく値も含まれる可能性がある場合、ステートメントと式の間の構文上の区別はそれほど有用ではないので、それを排除しました。 。Haskell、Icon、Lisp、およびMLはすべて、構文ステートメントを持たない言語であり、式しかありません。クラス構造のループと条件付きフォームも式と見なされ、それらには値がありますが、あまり興味深いものではありません。


9
私がここであなたを誤解していないのであれば、「(setf(third foo) 'goose)」はステートメントではなく式であると主張しているようです。 LispはCよりも10年以上古いため、Cは「[式とステートメントの間の]線を曖昧にする最も初期の一般的な言語」でした。その詳細を教えていただけませんか?
cjs

2
@Curt Sampson、それを別の質問として尋ねましたか?
ケリーS.フランス語

5
私が間違っていなければ、ではなく、にcallfunc(x = 2);渡さxれます。がfloatの場合、ではなく呼び出されます。あなたが渡した場合やC ++で、へ、および参照を取り、それを変更し、それが変化し、ではありません。callfunc2xcallfunc(float)callfunc(int)x=yfuncfuncxy
ガブリエル

上記の回答では、「Haskell、...はすべて、構文ステートメントを持たない言語であり、式しかありません」と書かれています。wherehaskellの節がステートメントではなく式と見なされる理由を知りたいです。 learnyouahaskell.com/syntax-in-functions#where
skgbanga

@skgbanga私whereは実際には式やステートメントではなく、関数宣言の一部だと思います。
アカンカ

22
  • 式は値を生成するものです:2 + 2
  • ステートメントは、プログラム実行の基本的な「ブロック」の1つです。

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

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

ANSI C文法からの抜粋です。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


2
ステートメントが何であるかについての誤ったロジック。宣言型プログラムも実行できますが、宣言型プログラムにはステートメントがありません。ステートメントは"副作用"であり、実行します。つまり、必須です。cf. 私の答え
シェルビームーアIII

15

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

例えば:

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

2つの間の大きな問題は、式をチェーン化できるのに対し、ステートメントはチェーン化できないことです。


6
確かにステートメントは連鎖させることができます。{stmt1; stmt2; stmt3;}はチェーンであり、それ自体も(複合)ステートメントです。
ヒューアレン

5
foo.voidFunc(1);void値を持つ式です。whileifステートメントです。
tzot 2009

ステートメントが連鎖しないことに興味があります。「if(x> 1)return;」のようになりますか?2つのステートメントを一緒にチェーンしていると見なされますか?
Simon Tewsi 2013年

1
@SimonTewsiサブステートメントとreturn見なされていると思います。
ラスタジェダイ

1
@SimonTewsiここのreturnステートメントは暗黙的にifステートメントのブロック内にあるため、ifステートメントの一部であり、チェーンされていません。コンパイラは単一行ブロックなので、ここで中括弧を省略できます。
user2597608

9

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

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

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


8

式とステートメントの構成可能性(連鎖可能性)の重要な違いの説明については、John Backusのチューリング賞の論文「プログラミングをフォンノイマンスタイルから解放できるか?」

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


5

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

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

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

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

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

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


ステートメントのタイプは一番下のタイプです。Voidボトムタイプではありません。私の答えをください。
シェルビームーアIII

1
されていない場合はnull型ボトム型(単一の値をnull)?ユニットタイプのvoidようなものではありませんか(ただし、単一の値にはアクセスできません)。
Mark Cidade

Ifはvoid決して戻って(例えば関数という関数の戻り値の型であるthrowエラーをS)、それはボトム型。それ以外の場合voidは、ユニットタイプです。あなたは発散できないステートメントがユニットタイプを持っていることは正しいです。しかし、発散する可能性のあるステートメントは一番下のタイプです。停止定理のため、通常、関数が発散しないことを証明できないため、単位はフィクションだと思います。下部の型は値を持つことができないため、単一の値を持つことはできませんnull
シェルビームーアIII

1
3年前に言ったことに関して、私がまだステートメントをvoid型または実際に任意の型があると考えるかどうかはわかりません。私がよく知っているステートメントベースの言語では、と、を格納または返すもの(たとえば、式、変数、メンバー、関数)のみが型を持つことができます。私は通常、一番下の型を空のセット(値なし)と考えているため、存在論的に存在しないものはすべてこの型になります。null値が本当にあるpseudovalue参照が存在しない何かを参照していることを示します。
Mark Cidade、2011

1
マーク回答の合理性を高く評価しました。基本的にあなたは私の言葉を口から出してくれました。そして、あなたがユニットポイントを上げるのは正しいことを認めたことは明らかです。私は同意すると思います。私はこれについて言及するつもりはありませんでしたが、一部の人々は私が否定的だと思っているようです。私はただ事実になりたいと思っています。
シェルビームーアIII

4

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


では、ステートメントは何をするのでしょうか?何もない?
シェルビームーアIII

1
それは何かをすることができますが、何にも評価されません。つまり、その結果を変数に代入することはできませんが、式では代入できます。
Matthew Schinckel、2011

そしてそのため、私の反対票が非常に多かった回答の状態のように、声明には副作用があるはずです。ステートメントが持つ可能性のある他のユーティリティは何ですか?NO-OPがステートメントであると見なされたとしても(構文解析の後に消去されるため、セマンティクスレイヤーではなく、文法では「ステートメント」にすぎません)、ここでは説明しません。文の一般的なユーティリティは一体です。
シェルビームーアIII 14

1
@ShelbyMooreIIIステートメントは何もする必要がなく、副作用もありません。たとえば、{}ステートメントです。単語を怖い引用符で囲んでも、それは変わりません。ステートメントは、セマンティクスを持つ構文構造です。「セマンティクスレイヤー」などというものはありません。あなたは実行について言及しているようです。あなたはあなたが正確にしようとしていると言いますが、あなたはそれで失敗しました。「反対投票者の無知」についてのあなたの不満は純粋なアドホミネムです。反対投票者の精神状態についての情報はありません。
ジムバルター、2015

ええ、知的な不正直を除いて誰もが間違っています。{}C#言語仕様のステートメントとして定義されています。
ジムバルター、2015

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()または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
)

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の後にtypeの式が続くことを要求することだけですvoid。の結果はdefault(void)voidであり、渡されるfuncはFunc<TValue, void>(と同等のAction<TValue>)形式である必要があります。

他の多くの答えは、式のようにステートメントを連鎖できないことを意味しますが、この考えがどこから来たのかはわかりません。;ステートメントの後に現れるは、2つの中置演算子と考えることができます。型の2つの式を取りvoid、それらをtypeの1つの式に結合しますvoid


ステートメントは式の特別なケースではありません。一部の言語(つまり、ほとんどのCの後継者)では、実際にはその逆です。
アカンカ

2

ステートメント->順次実行する指示
式->値を返す評価

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

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

ステートメントの例:

for
goto
return
if

(それらはすべて、実行の行(ステートメント)が別の行に進むことを意味します)

式の例:

2+2

(それは実行の考えを意味するのではなく、評価の意味を意味します)


副作用はどうですか?
オースティンヘンリー2012

@AustinHenleyそのための要件はありません。実際、式には必ず副作用があります。
アカンカ

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はどちらも、ローカル変数を識別する単純な名前です。これらの変数が式で使用されると、変数の値が取得され、式に使用されます。


私はむしろ書くif(number >= 0) return true; else return false;かもっと上手くいきたいですbool? IsPositive(int number) { if(number > 0) return true; else if(number < 0) return false; else return null;}:)
Mahdi Tahsildari 2013

1

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

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


1

私はここの答えのどれにも本当に満足していません。C ++(ISO 2008)の文法を見た。しかし、おそらく教授法とプログラミングのために、2つの要素を区別するには答えで十分かもしれません(ただし、現実はもっと複雑に見えます)。

ステートメントは0個以上の式で構成されますが、他の言語の概念にすることもできます。これは、文法の拡張バッカスナウアフォームです(ステートメントの抜粋):

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

C ++のステートメントと見なされる他の概念を見ることができます。

  • expression-statement sは自己説明的です(ステートメントは0個以上の式で構成できます。文法を注意深く読んでください、トリッキーです)
  • caseたとえば、ラベル付きステートメントです
  • selection-statementif if/elsecase
  • 反復文の sがありますwhiledo...whilefor (...)
  • ジャンプステートメント sがあるbreakcontinuereturn、(式を返すことができます)goto
  • 宣言ステートメント宣言のセットです
  • try-blockブロックを表すステートメントtry/catchです
  • 文法の下にもう少しあるかもしれません

これは、式の部分を示す抜粋です。

expression:
        assignment-expression
        expression "," assignment-expression
assignment-expression:
        conditional-expression
        logical-or-expression assignment-operator initializer-clause
        throw-expression
  • 式は割り当てであるか、割り当てを含むことが多い
  • 条件式は(音が誤解を招く)の演算子の使用を参照して(+-*/&|&&||、...)
  • スロー式 -え?throw句はあまりにも表現です

0

文は文法的に完全な文です。式はそうではありません。例えば

x = 5

「xは5を取得します」と読み取ります。これは完全な文です。コード

(x + 5)/9.0

「xプラス5すべてを9.0で割った値」と読み取ります。これは完全な文ではありません。ステートメント

while k < 10: 
    print k
    k += 1

完全な文です。ループヘッダーはそうではないことに注意してください。「while k <10」は従属節です。


while式はScalaなどの一部の言語です。文法をタイピングと混同しています。私の答えをください。
シェルビームーアIII

scalaのwhileループは次のとおりです。tutorialspoint.com/ scala / scala_while_loop.htm 述語があり、本体がないループは、文法的に完全な文ではありません。完全な表現ではありません。式として完成させるには本体が必要です。
ncmathsadist 2013年

whileボディ付きのA は、Scalaではまだ式です。それが副作用を生み出す場合、それは声明でもあるかもしれません。これは、私の反対投票の答えが許すものです(式は声明でもかまいません)。私の答えは唯一正しいものです。理解できない読者の皆さん、ごめんなさい。
シェルビームーアIII

文法的に完全とはどういう意味ですか?Cでは(x + 5)/9.0、ステートメントとして間違いなく独立できます。また、文法的に完全な場合は、有効なプログラムを意味します。Cでは、ステートメントを単一のプログラムとして独立させることはできません。
アカンカ

文法的に完全:完全な文を構成します。
ncmathsadist

0

これが、私が見つけた最も簡単な答えの1つです。

Anders Kaseorgが最初に回答

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

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

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

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


0

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

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

ステートメント:そのインスタンスが式の評価に関与する可能性のある構文カテゴリと、評価の結果の値(存在する場合)は、利用できることが保証されていません。

何十年も前のFORTRANのごく初期の状況に加えて、受け入れられた回答の表現とステートメントの両方の定義は明らかに間違っています。

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

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

(以下の根拠は元の質問に対する直接の回答ではありませんが、ここですでに回答されていることを明確にする必要があると思います。)

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

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

なぜ声明なのか?とにかく、歴史はすでに混乱しています。ほとんどの言語デザイナーは慎重に選択をしていません。

さらに悪いことには、型システムの愛好家(PLの歴史​​に十分に精通していない)にも、型システムは運用上のセマンティクスに関するより重要なルールの設計に重要なことをしなければならないという誤解を与えることさえあります。

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

たとえば、区切り文字なしの継続の従来の扱いに対する反対の中心的な議論として、タイピングの性質強調する人がいます。結論はやや妥当であり、合成された関数に関する洞察はOKですが(本質的にはあまりにも単純すぎる)、この引数は実際には_Noreturn any_of_returnable_types(サイドチャネル)アプローチを無視して(C11のように)エンコードするため、適切ではありませんFalsum厳密に言えば、予測不可能な状態の抽象的なマシンは「クラッシュしたコンピュータ」と同じではありません。


0

ステートメント指向プログラミング言語では、コードブロックはステートメントのリストとして定義されます。つまり、ステートメントは、構文エラーを発生させることなくコードブロック内に配置できる構文の一部です。

ウィキペディアは同様に単語ステートメントを定義しています

コンピュータプログラミングでは、ステートメントは、実行するアクションを表現する命令型プログラミング言語の構文単位です。そのような言語で書かれたプログラムは、一連の1つ以上のステートメントによって形成されます

後者のステートメントに注意してください。(この場合の「プログラム」は技術的に間違っていますが、CとJavaの両方がステートメントだけで構成されるプログラムを拒否するためです。)

ウィキペディアは単語表現を次のように定義しています

プログラミング言語の式は、その値を決定するために評価できる構文エンティティです

ただし、これはfalseです。Kotlinではthrow new Exception("")式ですが、評価されると例外をスローするだけで、値を返しません。

静的に型付けされたプログラミング言語では、すべての式に型があります。ただし、この定義は動的に型付けされたプログラミング言語では機能しません。

個人的には、式を、演算子または関数呼び出しで構成してより大きな式を生成できる構文の一部として定義しています。これは実際にはウィキペディアによる表現の説明に似ています:

これは、1つ以上の定数、変数、関数、および演算子の組み合わせであり、プログラミング言語が(優先順位と関連付けの特定の規則に従って)解釈し、別の値を生成する(ステートフル環境で「返す」)ように計算します。

しかし、問題は、次のような関数executeSomethingを与えられたCプログラミング言語にあります:

void executeSomething(void){
    return;
}

executeSomething()式ですか、それともステートメントですか?私の定義によると、これはステートメントです。MicrosoftのC参照文法で定義されているように、

void型の式の(存在しない)値を使用することはできません。また、void式を(暗黙的または明示的な変換によって)void以外の型に変換することもできません。

しかし、同じページは、そのような構文が式であることを明確に示しています。


-6

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

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

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

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


2
この区別は、式のタイプとは関係ありません。構文的に定義されたステートメントには、多くの言語でタイプがまったくありません。理論的にはそのような用語にタイプを割り当てることには反対ではありませんが、異なる処理@pragmaまたは/*comment*/論理的に一貫性がありません。
FrankHB

-11

最も正確には、ステートメントが持っている必要があり、「副作用」(すなわちことが不可欠に)と式はしなければならない持っている値の種類(すなわちないボトム型)を。

ステートメントタイプは単位タイプですが、定理の停止により単位はフィクションなので、ボトムタイプと言いましょう。


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

この件に関してウィキペディアが何を言わなければならないか見てみましょう。

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

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

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


5
ステートメントに副作用がある必要はありません。たとえば、Python passではステートメントです。これはノーオペレーションであり、何にも評価されません。
Matthew Schinckel、2011

9
-1これは誤りです。ステートメントに副作用がある必要はありません。C#言語仕様のセクション1.5を参照してください。ステートメントに副作用が必要であることを指定するだけでなく、副作用がない可能性のあるいくつかのステートメントもリストします。
NullUserException

2
@NullUserExceptionそのセクションを読みました。宣言、式、選択、反復、およびジャンプのステートメントはすべて、副作用を引き起こす可能性があります。しかし、RT式がある場合、それはステートメントではありません。仕様は式とステートメントを同等と見なしていると思いますが、この質問ではそれらの違いを尋ねました。したがって、質問に答えがないか、C#仕様を文字どおりに解釈しすぎています。上位投票の答えは、私がしたことを言おうとすることです。しかし、「何かをする」というのは意味がありません。「副作用」は「何かをする」と言う意味のある方法です。ただ逆流するだけでなく、考えなければなりません。
シェルビームーアIII

13
@ShelbyMooreIIIあなたは正しいです。公式ドキュメントは間違っています。Eric Lippertの外のSOで最も尊敬されているC#ポスターであるMarc GravellとJon Skeetは間違っています。私と、あなたに反対票を投じ、私たちの立場を説明するコメントを残した他のすべての人は間違っています。あなたが正しいです。SOの他のすべてよりもはるかに賢いので、あなたは明らかに彼らが話していることを知っている唯一の人です。
NullUserException

3
ステートメント、式、キャスト、変換などの概念の正確な定義を知っていても、日常のプログラミングタスクの99.999%に影響はありません。考えています。また、ほとんどの人はHaskellとScalaを気にしません。
NullUserException
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.