Chapter 3: Your own types
Pizza pricing
- recursive types
- maps
- ?
ExtraSauce(Pizza) holds another pizza, so a pizza can be
wrapped any number of times. The price function peels one layer per call.
%{Margherita: 7, …} is a map literal, compiled to
dict.from_list.
dict.get(price_map, p)? uses the ? operator: if
the lookup is Ok, you get the value; if it is
Error, the whole function returns that error immediately.
It works in the middle of an expression, here even inside a
case branch.
import gleam/dict
pub type Pizza {
Margherita
Caprese
Formaggio
ExtraSauce(Pizza)
ExtraToppings(Pizza)
}
def price_map() {
%{
Margherita: 7,
Caprese: 9,
Formaggio: 10,
}
}
def calc_pizza_price(p: Pizza, price_map, acc: Int) {
case p {
ExtraSauce(s) -> calc_pizza_price(s, price_map, acc + 1)
ExtraToppings(s) -> calc_pizza_price(s, price_map, acc + 2)
_ -> acc + dict.get(price_map, p)? |> Ok
}
}
def pizza_price(p: Pizza) {
case calc_pizza_price(p, price_map(), 0) {
Ok(price) -> price
_ -> panic as "Invalid pizza"
}
}
pub def main() {
echo pizza_price(ExtraToppings(ExtraSauce(ExtraSauce(Margherita))))
}import gleam/dict
import gleam/result
pub type Pizza {
Margherita
Caprese
Formaggio
ExtraSauce(Pizza)
ExtraToppings(Pizza)
}
fn price_map() {
dict.from_list([#(Margherita, 7), #(Caprese, 9), #(Formaggio, 10)])
}
fn calc_pizza_price(p: Pizza, price_map, acc: Int) {
case p {
ExtraSauce(s) -> calc_pizza_price(s, price_map, acc + 1)
ExtraToppings(s) -> calc_pizza_price(s, price_map, acc + 2)
_ -> {
use bea_try_406 <- result.try(dict.get(price_map, p))
acc + bea_try_406 |> Ok
}
}
}
fn pizza_price(p: Pizza) {
case calc_pizza_price(p, price_map(), 0) {
Ok(price) -> price
_ -> panic as "Invalid pizza"
}
}
pub fn main() {
echo pizza_price(ExtraToppings(ExtraSauce(ExtraSauce(Margherita))))
}src/e12_pizza_pricing.bea:35
11An exercism exercise from the Gleam track, solved in Bea: beacode/src/e12_pizza_pricing.bea