Lecture 05
Records, Variants,
Match Expressions
Programming Languages
UW CSE 341 - Spring 2021
What is a Programming Language?
What is a Programming Language?
We will mostly focus on semantics and idioms
Building Types
Anatomy of types in ANY Language
Languages generally provide three kinds of building blocks to define types
The ability to nest and mix-and-match makes these building blocks even more powerful!
😍 Composition 😍
Example Types From Building Blocks
Example Types From Building Blocks
Types provide a compact language for expressing the “shape” of data!
Today: Records and Variants
Records : Define
Syntax: type t = { f1 : t1; … ; fN : tN }
Adds new (record) type t and fields f1, …, fN
Must define a record type before you can build or use
Example
As usual, see the accompanying code
Records : Build
Syntax: { f1 = e1; … ; fN = eN }
Type Checking
Elements separated by semicolons “ ; ” ⚠️
Get very weird error messages otherwise ⚠️
Records : Build
Syntax: { f1 = e1; … ; fN = eN }
Evaluation
Records of values are values.
Records : Use
Syntax: e.f
Type Checking
Evaluation
Tuples vs. Records
Today: Records and Variants
✅
Variants are not like records!
One-of types are not each-of types!
Enumerations
type si_unit =
| Second | Meter | Kilogram | Ampere
| Kelvin | Mole | Candela
Variant definition syntax/semantics
type si_unit =
| Second | Meter | Kilogram | Ampere
| Kelvin | Mole | Candela
Build
type si_unit =
| Second | Meter | Kilogram | Ampere
| Kelvin | Mole | Candela
Bool
Anyway, we can now define enumerations and build values of them, so need a way to use values of them
Use variant types with match expressions
let string_of_si_unit u =
match u with
| Second -> "second"
| Meter -> "meter"
| Kilogram -> "kilogram"
| Ampere -> "ampere"
| Kelvin -> "kelvin"
| Mole -> "mole"
| Candela -> "candela"
let s =
string_of_si_unit Ampere
Back to bool
match e1 with
| true -> e2
| false -> e3
if e1 then e2 else e3
Beyond enumerations
As promised, ML variant types are much more powerful
Variants: Define
Syntax: type t = | C1 [of t1] | … | CN [of t1]
Adds new (variant) type t and constructors C1, …, CN
Must define a variant type before you can build or use
type silly =
| A of int * bool * string list
| Foo of string
| Pizza
Variants: Build
Syntax: C e
Type-checking:
Evaluation: Evaluate e to a value v and C v is a value
type silly =
| A of int * bool * string list
| Foo of string
| Pizza
Match expressions, the big picture
A powerful and concise expression form that combines three things:
This is elegant (once you get used to it) and avoids errors like forgetting cases or trying to extract the “wrong” data for the tag you have
Variants: Use
[will generalize this soon!]
Syntax:
match e with P1 -> e1 | … | PN -> eN
For now, each pattern should be one of these:
where x1, …, xn and x are variables
type silly =
| A of int * bool * string list
| Foo of string
| Pizza
Patterns
Patterns are not expressions, even though they kind of look like them
They are used for matching and to bind local variables when they match
Evaluation rules (again, will generalize soon)
match e with P1 -> e1 | … | PN -> eN
Type-checking
Lots going on, toward two goals:
Type-checking
match e with P1 -> e1 | … | PN -> eN