次のF#行を見ています
for i = 0 to i=10 do
Console.WriteLine("Hello")
上記の行は、式ではなくステートメントではないのでしょうか?
すべてが F# の式であってはなりませんか?
既に述べたように、F# のすべての構文構造は式です。F# はステートメントと式を区別しません (したがって、Robert が投稿した WikiPedia の引用は少し誤解を招くと思います - F# にはステートメントがありません)。
実際には、上記は完全には当てはまりません。F# の計算式にlet!
は、 not式などの一部の構成要素があるためですが、それは無視できます。
どういう意味ですか?C# では、for
メソッド呼び出しの構文は次のように定義されます。
statement := foreach(var v in <expression>) <statement>
| { <statement> ... <statement> }
| <expression>;
| (...)
expression := <expression>.<ident>(<expression>, ..., <expression>)
| <literal>
| <expression> + <expression>
| (...)
これは非常に単純化されていますが、これでお分かりいただけるはずです。ステートメントとは、値に評価されないものです。これは、foreach
ループ (その他のループ)、ステートメント ブロック (複数のステートメントを含む)、またはセミコロンを含む式 (式の結果void
が無視されるか無視される) のいずれかです。式は、たとえば、メソッド呼び出し、プリミティブ リテラル (string、int)、または二項演算子です。
これは、C# で特定のものを記述できないことを意味します。たとえば、メソッド呼び出しの引数をステートメントにすることはできません (ステートメントは値に評価されないためです!)
一方、F# では、すべてが式です。これは、構文カテゴリが 1 つしかないことを意味します。
expression := for v in <expression> do <expression>
| <expression>; <expression>
| <expression>.<ident>(<expression>, ..., <expression>)
| <literal>
| <expression> + <expression>
| (...)
これは、F# ではすべての構文構造が式でfor
あり、その他のループを含むことを意味します。の本体for
も式ですが、式が何らかの値 (つまり42
) に評価された場合は意味がありません。そのため、型では本体の結果がunit
(情報を持たない) である必要があります。同様に、sequencing( <expr>; <expr>
) の最初の式が返されます。sequencingunit
の結果は、2 番目の式の結果です。
これにより、言語はより単純で統一されたものになりますが、いくつかの奇妙なことを書くことができます:
let x = (for i in 0 .. 10 do printfn "%d" i); 42
これにより、 から0
までの数値が出力され10
、値が と定義x
されます42
。割り当ては式 ( <expr>; <expr>
) のシーケンスであり、最初の 1 つはfor
ループ (unit
何も評価されないため、型は です) であり、2 番目の式は42
であり、42 に評価されます。
if ステートメントやループを含む F# のすべてのステートメントは、明確な戻り値の型を持つ構成可能な式です。値を返さない関数と式の戻り値の型は unit です。
()
F# のような言語では、ステートメントはtypeの値を返す単なる式unit
です。型にはunit
値が 1 つしかないため、情報が伝達されないため、型 unit の値を返すことは、コンソールへの出力やディスクへの書き込みなど、「何かをしている場合、それは副作用によるものです」と言っています。
すべてが F# の式であるとは限らないことに注意してください。型定義は式ではありません。パターンは表現ではありません。等々...