Option
Encapsulation of optional value
Import
_ <- fat.extra.Option
Error type is automatically imported along with this import
Types
This library introduces two main constructs: Some and None, which are special cases of the Option type, providing a way to represent optional values, encapsulating the presence (Some) or absence (None) of a value.
Prototype members
| Name | Signature | Brief |
|---|---|---|
| isEmpty | <> Boolean | Check if the option is None |
| nonEmpty | <> Boolean | Check if the option is Some |
| size | <> Number | Return 1 if Some, 0 if None |
| toText | <> Text | Return the text literal |
| freeze | <> Void | Make the value immutable |
| get | <> Any | Return value or raise NoSuchElement |
| getOrElse | (default: Any): Any | Return value or default if None |
| map | (fn: Method): Option | Apply method to contained value |
| flatMap | (fn: Method/Option): Option | Apply method that returns Option |
| filter | (predicate: Method): Option | Filter value by predicate |
| toList | <> List | Convert option to List |
| concrete | <> Option | Resolve option to Some or None |
Constants
none, the singleton literal of theNonetype (available since version4.2.x)
Prototype support
As of version 4.2.x, importing the Option type enables the .some method on all native types:
30.some # => Some(30)
'msg'.some # => Some('msg')
...
null.some # => None (special case)
This provides a more fluent syntax for working with optional values.
Usage example
_ <- fat.extra.Option
# Creating options
x = Some(5) # equivalent to Option(5).concrete
y = None() # equivalent to Option().concrete or just none
# Working with options
isEmptyX = x.isEmpty # false
isEmptyY = y.isEmpty # true
valX = x.getOrElse(0) # 5
valY = y.getOrElse(0) # 0
# Applying a transformation
transformedX = x.map(v -> v * 2).getOrElse(0) # 10
transformedY = y.map(v -> v * 2).getOrElse(0) # 0
# Lifting values to option
label: Text = Option(opVal).concrete >> {
Some => 'some value' # case where opVal is not null
None => 'no value' # case where opVal is null
}
Option in Functional Programming
In FatScript, null is integrated as a first-class citizen, enabling native types, in most cases, to handle absent values without necessitating additional constructs for safety. Consequently, the Option type is included in the extra package as a syntactic sugar.
It allows explicit encapsulation of optional values for semantic clarity or adherence to certain functional programming paradigms. An example of its utility is demonstrated in the Scope type, which includes a maybe method alongside the standard value retrieval syntax:
myScope('key')returns the value associated withkeyornullif the key does not exist.myScope.maybe('key')provides anOptionwrapped value, distinguishing explicitly between the existence (Some) and absence (None) of a value.
Semantic handling of missing values
One of the key benefits of using the Option type is its ability to handle operations with potentially missing values semantically and safely. This feature is particularly useful in primitive operations or data transformations where null values might otherwise lead to errors. For example, consider a scenario where you need to sum a number with a value that may not be present:
# Assuming eggsBought is defined and has a value
eggsBought: Number = ...
# fridge.maybe('egg') retrieves the number of eggs in the fridge as an Option
# If 'egg' is not present, it defaults to 0, avoiding null-related errors
totalEggs: Number = fridge.maybe('egg').getOrElse(0) + eggsBought
Performance considerations
The use of Option types introduces computational overhead due to function calls needed to manipulate values and additional memory stemming from their underlying structure. While the benefits of safety and expressiveness are significant, the performance cost could become noticeable in tight loops or when processing large datasets.