Question

I am looking at the following F# line

for i = 0 to i=10 do
   Console.WriteLine("Hello")

An I am wondering that isn't the above line a statement as opposed to an expression?

Shouldn't everything be an expression in F#?

Was it helpful?

Solution

As already said, every syntactical construct in F# is an expression. F# does not distinguish between statements and expressions (and so I'd say that the WikiPedia quote posted by Robert is a bit misleading - F# does not have statements).

Actually, the above is not fully true, because some constructs in F# computation expressions such as let! are not expressions, but we can ignore that.

What does that mean? In C#, the syntax of for and method calls is defined something like this:

statement  := foreach(var v in <expression>) <statement>
            | { <statement> ... <statement> }
            | <expression>;
            | (...)

expression := <expression>.<ident>(<expression>, ..., <expression>)
            | <literal>
            | <expression> + <expression>
            | (...)

This is very simplified, but it should give you the idea - a statement is something that does not evaluate to a value. It can be foreach loop (other loops), a statement block (with multiple statements) or an expression with semicolon (where the result of the expression is void or is ignored). An expression is, for example, method call, primitive literal (string, int) or a binary operator.

This means that you cannot write certain things in C# - for example, the argument of method call cannot be a statement (because statements do not evaluate to a value!)

On the other hand, in F#, everything is an expression. This means there is just a single syntactic category:

expression := for v in <expression> do <expression>
            | <expression>; <expression>
            | <expression>.<ident>(<expression>, ..., <expression>)
            | <literal>
            | <expression> + <expression>
            | (...)

This means that in F# all syntactic constructs are expressions, including for and other loops. The body of for is also an expression, but it would not make sense if the expression evaluated to some value (i.e. 42), so the types require that the result of the body is unit (which does not carry any information). Similarly, the first expression in sequencing (<expr>; <expr>) should return unit - the result of sequencing is the result of the second expression.

This makes the language simpler and more uniform, but you can write some odd things:

let x = (for i in 0 .. 10 do printfn "%d" i); 42

This will print numbers from 0 to 10 and then define a value x to be 42. The assignment is a sequencing of expressions (<expr>; <expr>) where the first one is for loop (that has a type unit, because it does not evaluate to anything) and the second one is 42, which evaluates to 42.

OTHER TIPS

Every statement in F#, including if statements and loops, is a composable expression with a definite return type. Functions and expressions that do not return any value have a return type of unit.

http://en.wikipedia.org/wiki/F_Sharp_(programming_language)

In languages like F# statements are just expressions that return the value () of type unit. As the unit type has only one value it conveys no information so returning the value of type unit is saying "if I'm doing anything then it is by way of a side effect" like printing to the console or writing to disk.

Note that not everything is an expression in F#. Type definitions are not expressions. Patterns are not expressions. And so on...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top