Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

So is everything an expression in F#?

Tags:

f#

unit-type

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#?

like image 773
Knows Not Much Avatar asked Dec 15 '22 22:12

Knows Not Much


2 Answers

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.

like image 105
Tomas Petricek Avatar answered Dec 30 '22 20:12

Tomas Petricek


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)

like image 22
Robert Harvey Avatar answered Dec 30 '22 19:12

Robert Harvey