Pattern in let and match
There are two common places to use a pattern: let
and match
.
In this example, we define a Resource
type that describes a file system.
The Resource
can be a text file, an image, or a folder associated with more files.
Pattern in let statement
In a let
statement, the left side of =
can be a pattern.
We know that assets
is a folder so we just use let Folder(top_level) = assets
to match it and extract the value into the immutable variable top_level
.
You may notice that there is a partial match warning because the resource can also be Image
or TextFile
.
Partial matches make the program more fragile: the pattern matching may fail in other cases and lead to the program aborting.
Practically, the match
expression is used more frequently than the let
statement.
Pattern in match expression
The count
function traverses the input res
recursively and returns the count of Image
and TextFile
, using a match
expression.
Match expressions have first match semantics. They will try to find the first matching pattern sequentially from the first case to the last case and execute the corresponding matched expression. If no pattern matches, the program will abort.
The match expression has an Int
return value because all the cases result in the same value type Int
.
Patterns can be nested. If you don't care about the data associated with the enum constructor, you can use the any pattern, written as _
, instead of introducing a new variable.
The underscore means that the value is discarded.
enum Resource {
TextFile(String)
Image(String)
Folder(Map[String, Resource])
}
let assets : Resource = Folder(
{
"readme.md": TextFile("hello world"),
"image.jpg": Image("https://someurl1"),
"folder1": Folder(
{
"src1.mbt": TextFile("some code1"),
"src2.mbt": TextFile("some MoonBit code 2"),
},
),
"folder2": Folder(
{
"src3.mbt": TextFile("some code3"),
"image2.jpg": Image("https://someurl2"),
},
),
},
)
fn main {
let Folder(top_level) = assets
println("we have items in the root folder:\n \{top_level.keys()}")
println("resource count: \{count(assets)}")
}
fn count(res : Resource) -> Int {
match res {
Folder(map) => {
let mut sum = 0
for name, res in map {
sum += count(res)
}
sum
}
TextFile(_) => 1
Image(_) => 1
}
}