F# how to write an empty statement

2019-04-18 22:43发布

问题:

How can I write a no-op statement in F#?

Specifically, how can I improve the second clause of the following match statement:

match list with
    | [] -> printfn "Empty!"
    | _ -> ignore 0

回答1:

Use unit for empty side effect:

match list with
  | [] -> printfn "Empty!"
  | _ -> ()


回答2:

The answer from Stringer is, of course, correct. I thought it may be useful to clarify how this works, because "()" insn't really an empty statement or empty side effect...

In F#, every valid piece of code is an expression. Constructs like let and match consist of some keywords, patterns and several sub-expressions. The F# grammar for let and match looks like this:

<expr> ::= let <pattern> = <expr>
           <expr>
       ::= match <expr> with
           | <pat> -> <expr>

This means that the body of let or the body of clause of match must be some expression. It can be some function call such as ignore 0 or it can be some value - in your case it must be some expression of type unit, because printfn ".." is also of type unit.

The unit type is a type that has only one value, which is written as () (and it also means empty tuple with no elements). This is, indeed, somewhat similar to void in C# with the exception that void doesn't have any values.

BTW: The following code may look like a sequence of statements, but it is also an expression:

printf "Hello "
printf "world"

The F# compiler implicitly adds ; between the two lines and ; is a sequencing operator, which has the following structure: <expr>; <expr>. It requires that the first expression returns unit and returns the result of the second expression.

This is a bit surprising when you're coming from C# background, but it makes the langauge surprisingly elegant and consise. It doesn't limit you in any way - you can for example write:

if (a < 10 && (printfn "demo"; true)) then // ...

(This example isn't really useful - just a demonstration of the flexibility)



标签: f# unit-type