Reputation: 3044
I'm pretty new to functional programming and I've started looking at the documentation for match
statements and in the example I came across here gitpages and cut and pasted to my question below:
let rec fib n =
match n with
| 0 -> 0
| 1 -> 1
| _ -> fib (n - 1) + fib (n - 2)
I understand that let
is for static binding in this case for a recursive function called fib which takes a parameter n. It tries to match n with 3 cases. If it's 0, 1 or anything else.
What I don't understand is what the |
symbol is called in this context or why it is used? Anything I search for pertaining to f-sharp pipe takes me to this |>
which is the piping character in f sharp.
What is this |
used for in this case? Is it required or optional? And when should be and shouldn't I be using |
?
Upvotes: 3
Views: 964
Reputation: 36738
To expand on Tomas's excellent answer, here are some more of the various uses of |
in F#:
In match expressions, |
separates the various patterns, as Tomas has pointed. While you can write the entire match
expression on a single line, it's conventional to write each pattern on a separate line, lining up the |
characters, so that they form a visual indicator of the scope of the match
statement:
match n with
| 0 -> "zero"
| 1 -> "one"
| 2 -> "two"
| 3 -> "three"
| _ -> "something else"
Discriminated Unions (or DUs, since that's a lot shorter to type) are very similar to match
expressions in style: defining them means listing the possibilities, and |
is used to separate the possibilities. As with match
expressions, you can (if you want to) write DUs on a single line:
type Option<'T> = None | Some of 'T
but unless your DU has just two possibilities, it's usually better to write it on multiple lines:
type ContactInfo =
| Email of string
| PhoneNumber of areaCode : string * number : string
| Facebook of string
| Twitter of string
Here, too, the |
ends up forming a vertical line that draws the eye to the possibilities of the DU, and makes it very clear where the DU definition ends.
Active patterns also use |
to separate the possibilities, but they also are wrapped inside an opening-and-closing pair of |
characters:
let (Even|Odd) n = if n % 2 = 0 then Even else Odd // <-- Wrong!
let (|Even|Odd|) n = if n % 2 = 0 then Even else Odd // <-- Right!
Active patterns are usually written in the way I just showed, with the |
coming immediately inside the parentheses, which is why some people talk about "banana clips" (because the (|
and |)
pairs look like bananas if you use your imagination). But in fact, it's not necessary to write the (|
and |)
characters together: it's perfectly valid to have spaces separating the parentheses from the |
characters:
let (|Even|Odd|) n = if n % 2 = 0 then Even else Odd // <-- Right!
let ( |Even|Odd| ) n = if n % 2 = 0 then Even else Odd // <-- ALSO right!
The pipe operator |>
and the Boolean-OR operator ||
are not at all the same thing as uses of the |
operator. F# allows operators to be any combination of symbols, and they can have very different meanings from an operator that looks almost the same. For example, >=
is a standard operator that means "greater than". And many F# programs will define a custom operator >>=
. But although >>=
is not defined in the F# core library, it has a standard meaning, and that standard meaning is NOT "a lot greater than". Rather, >>=
is the standard way to write an operator for the bind
function. I won't get into what bind
does right now, as that's a concept that could take a whole answer all on its own to go through. But if you're curious about how bind
works, you can read Scott Wlaschin's series on computation expressions, which explains it all very well.
Upvotes: 5
Reputation: 243096
The |
symbol is used for several things in F#, but in this case, it serves as a separator of cases of the match
construct.
The match
construct lets you pattern match on some input and handle different values in different ways - in your example, you have one case for 0
, one for 1
and one for all other values.
Generally, the syntax of match
looks like this:
match <input> with <case_1> | ... | <case_n>
Where each <case>
has the following structure:
<case> = <pattern> -> <expression>
Here, the |
symbol simply separates multiple cases of the pattern matching expression. Each case then has a pattern and an expression that is evaluated when the input matches the pattern.
Upvotes: 6