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"
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
"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.
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
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:
"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.
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?