Instructor: If/else allows us to perform different expressions based on the provided condition. The condition inside the parenthesis must be Boolean and determines if the first or the second branch is evaluated.
It even seems like good morning's returned, but if you try to assign it to a variable the REPL correctly complains about the syntax error. Back to Reason.
While the fact that if is an expression can be quite useful, it also comes with its limitations. Every branch -- often if/else -- needs to evaluate to the same type, which means we can't do the following. That's because in the case, no else branch is provided. It automatically returns the type unit for a not defined else case, like this example.
This means we can still use if for side effects like printing a value as long as the last statement returns the type unit. Print_endline does so. Let's move on to the switch expression.
It accepts a value and matches it against the patterns. The case of the matching pattern, which has to be an expression, then is evaluated. In its simplest form, pattern just matches for structural equality. For example, when matching integers, we know that one equals one but doesn't equal zero.
Let's see an example. For a lamp UI interface, we want to convert zero and one to the strings of off and on, pretty straightforward using switch and matching these two numbers. Worked as expected. The string value on is bound to the name lamp. By the way, this is possible because in Reason, switch is also an expression.
There is one issue, though. We get a warning that our pattern matching is not exhaustive, and it provides us with a hint that we didn't cover the example value two. It's only a warning, so we could ignore it and move on prototyping our application.
On the other hand, who knows what a possible data source might send? As long as it's an integer, we could even receive two or three at some point. To rule out potential bugs, we could cover the whole integer space, make sure the lamp is turned off for every input other than one.
Covering the whole integer range would be quite tedious, though. That's why Reason provides us with a special fall-through case. Will our match conditions go to that branch then? To implement such a fall-through case, we can either provide a name like we would do for a let binding, or an underscore in case the value isn't used in a case. First, we explore the version using the underscore.
Now we can change the provided value to, for example, 1003, and still get a desired result. If we want to extract the value, we can give it a name. We can use the name, for example to log a warning, and still return the valid result of. Pattern matching can be done with any type. Here is an example matching a string.
So far, so good. Until now, we only use pattern matching using structural equality and the fall-through case. Pattern matching, though, has a lot more features. We will explore them later in a pattern matching lesson.