In Elmish apps, we often find ourselves in situations where the element to be displayed to the user is determined by processing a list of option values. In such cases, often the elements that are stored in Some
option members are rendered on the screen whereas the members with the None
value are discarded. Think of buttons and other UI elements, or even the pages themselves.
In this short blogpost, I will show you a couple of very simple ways to yield an option value inside a list and explain what is involved as well as how the two approaches compare.
An Option Value
For demonstration purposes, I will create an option of string.
let maybeAValue = Some "Test"
Pattern Matching
One way we often see option types being unwrapped in a list comprehension expression looks like this:
let firstVersion = [
"Hello"
"There"
match maybeAValue with
| Some v -> v
| None -> ()
]
As you can see, the firstVersion
list has two string literal members that read "Hello"
and "There"
. Its third member in this case is going to be "Test" since Some "Test"
is what we've bound to the maybeAValue
identifier. The way that we determine the value of the third member is to perform a pattern match on the maybeAValue
identifier and return its value if it's a Some
. If it's a None
, unit is returned and the list only has two members.
Also, note that in this case, all the other members of the list except the last one fits into a single whereas the we break the pattern match for the last member into three lines.
Option.toList
and yield!
Now, let's look at an alternative approach that uses the Option.toList
method and the yield!
keyword that makes things a little more concise.
let secondVersion = [
"Hello"
"There"
yield! maybeAValue |> Option.toList
]
Compare this snippet of code to the one before. As you can see, what was previously achieved in three lines is now achieved in a single line. What enables us to do this is the yield!
keyword and the toList
method of the Option
module. When the third line inside the list comprehension expression is run, the string option will be passed into the Option.toList
method. This method will return a list containing the value inside the maybeAValue
if it's a Some
, and an empty list if it's a None
.
What yield!
does is to simple take the members of an inner sequence and insert them into the outer sequence. In our specific case, the inner sequence is a list with a single member – "Test"
. And so in the final analysis, the secondVersion
list will contain three members: "Hello"
, "There"
and "Test"
. However, if we've assigned None
to the maybeAValue
identifier, we would again have a list with only the initial two members at the end.
Summary
I am of the opinion that even if the case is as simple as what we've looked at here, we should go with the simpler, more concise option to improve the readability of the bigger picture and keep things tidier. The fact that in the second approach we don't lose much of the readability even if we write all of the code for yielding the option into a single line makes it much more preferable to use for me. What do you think? Now that you are aware of both of these approaches, which one would you pick when you need to yield an option into a list the next time around?