{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "e170df5a-7f85-4133-972c-4cb137eb4460",
   "metadata": {},
   "source": [
    "# PLC 2026, Lecture 11, 17 February 2026"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9f6b0831-5e20-4945-8714-94b8a16860c3",
   "metadata": {},
   "source": [
    "### Enumerated types"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "17a87693-0d80-40d0-90f8-24c9cc44eb8a",
   "metadata": {},
   "source": [
    "- Simplest form, choice of constants"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "deb5de1a-3298-439f-abc9-11d190d9d9b1",
   "metadata": {},
   "outputs": [],
   "source": [
    "enum IpAddrKind {\n",
    "    V4,\n",
    "    V6,\n",
    "}\n",
    "\n",
    "let four = IpAddrKind::V4;\n",
    "let six = IpAddrKind::V6;\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "73fb7716-eeec-4948-9c09-e300bb36e432",
   "metadata": {},
   "outputs": [
    {
     "ename": "Error",
     "evalue": "`IpAddrKind` doesn't implement `Debug`",
     "output_type": "error",
     "traceback": [
      "\u001b[31m[E0277] Error:\u001b[0m `IpAddrKind` doesn't implement `Debug`"
     ]
    }
   ],
   "source": [
    "four"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2501864b-9822-4ced-b8a0-4d7ca864c5cf",
   "metadata": {},
   "source": [
    "- Add special directive to get around the `Debug` issue"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "4dbbf2f5-6908-4eec-9bde-483879cbf7e4",
   "metadata": {},
   "outputs": [],
   "source": [
    "#[derive(Debug)]\n",
    "enum IpAddrKind {\n",
    "    V4,\n",
    "    V6,\n",
    "}\n",
    "\n",
    "let four = IpAddrKind::V4;\n",
    "let six = IpAddrKind::V6;\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "7d56865e-cecc-4d1b-9afa-c742c378f28f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "V4"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "four"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9f089098-1424-4dc4-bf84-5de2da6ce12a",
   "metadata": {},
   "outputs": [
    {
     "ename": "Error",
     "evalue": "`IpAddrKind` doesn't implement `std::fmt::Display`",
     "output_type": "error",
     "traceback": [
      "\u001b[31m[E0277] Error:\u001b[0m `IpAddrKind` doesn't implement `std::fmt::Display`",
      "   \u001b[38;5;246m╭\u001b[0m\u001b[38;5;246m─\u001b[0m\u001b[38;5;246m[\u001b[0mcommand_6:1:1\u001b[38;5;246m]\u001b[0m",
      "   \u001b[38;5;246m│\u001b[0m",
      " \u001b[38;5;246m1 │\u001b[0m \u001b[38;5;249mp\u001b[0m\u001b[38;5;249mr\u001b[0m\u001b[38;5;249mi\u001b[0m\u001b[38;5;249mn\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249ml\u001b[0m\u001b[38;5;249mn\u001b[0m\u001b[38;5;249m!\u001b[0m\u001b[38;5;249m(\u001b[0m\u001b[38;5;249m\"\u001b[0m\u001b[38;5;54m{\u001b[0m\u001b[38;5;54mf\u001b[0m\u001b[38;5;54mo\u001b[0m\u001b[38;5;54mu\u001b[0m\u001b[38;5;54mr\u001b[0m\u001b[38;5;54m}\u001b[0m\u001b[38;5;249m\"\u001b[0m\u001b[38;5;249m)\u001b[0m\u001b[38;5;249m;\u001b[0m",
      " \u001b[38;5;240m  │\u001b[0m           \u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m┬\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m  ",
      " \u001b[38;5;240m  │\u001b[0m              \u001b[38;5;54m╰\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m `IpAddrKind` cannot be formatted with the default formatter",
      " \u001b[38;5;240m  │\u001b[0m ",
      " \u001b[38;5;240m  │\u001b[0m \u001b[38;5;115mNote\u001b[0m: help: the trait `std::fmt::Display` is not implemented for `IpAddrKind`",
      "\u001b[38;5;246m───╯\u001b[0m"
     ]
    }
   ],
   "source": [
    "println!(\"{four}\");"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "13414f6f-4343-4e88-8c27-90f23ee37694",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "V4\n"
     ]
    }
   ],
   "source": [
    "println!(\"{four:?}\");"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "10c9a9ff-79eb-46c3-a339-afc04b8db4be",
   "metadata": {},
   "source": [
    "- Options can be parameterized"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "83483cfc-8fb3-4c5f-80f2-f6ff1322d44d",
   "metadata": {},
   "outputs": [],
   "source": [
    "#[derive(Debug)]\n",
    "enum IpAddr {\n",
    "    V4(String),\n",
    "    V6(String),\n",
    "}\n",
    "\n",
    "let home = IpAddr::V4(String::from(\"127.0.0.1\"));\n",
    "let loopback = IpAddr::V6(String::from(\"::1\"));\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "ea152b9b-5b16-47df-a687-f022e9714530",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "V6(\"::1\")"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "loopback"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0f9ac18f-356e-4f2f-b40b-c568721c790d",
   "metadata": {},
   "source": [
    "- Options can have different types of associated values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "fa3b0d4b-880b-466d-8f4d-9a567ce48fd7",
   "metadata": {},
   "outputs": [],
   "source": [
    "#[derive(Debug)]\n",
    "enum IpAddr {\n",
    "    V4(u8, u8, u8, u8),\n",
    "    V6(String),\n",
    "}\n",
    "\n",
    "let home = IpAddr::V4(127, 0, 0, 1);\n",
    "let loopback = IpAddr::V6(String::from(\"::1\"));\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "f125dacb-f289-4a4d-a559-581056209766",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "V4(127, 0, 0, 1)"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "home"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "913d5584-8c0b-4e23-9464-7349c6212fb3",
   "metadata": {},
   "source": [
    "- Like a `struct`, can attach functions to an `enum`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "8ed4dbbb-6778-4d0b-b9d5-b6e83dd43cd1",
   "metadata": {},
   "outputs": [],
   "source": [
    "#[derive(Debug)]\n",
    "enum Message {\n",
    "    Quit,\n",
    "    Move { x: i32, y: i32 },\n",
    "    Write(String),\n",
    "    ChangeColor(i32, i32, i32),\n",
    "}\n",
    "\n",
    "impl Message {\n",
    "    fn call(&self) {\n",
    "        // method body would be defined here\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "59821e26-ce81-4e35-87b6-488446c656b9",
   "metadata": {},
   "source": [
    "- Typical usage"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "8f4db606-19b4-4f36-b5ed-7c40c0f4edf6",
   "metadata": {},
   "outputs": [],
   "source": [
    "let m = Message::Write(String::from(\"hello\"));\n",
    "m.call();"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4bff27ac-7093-4cb6-ba96-da7b754d7a7a",
   "metadata": {},
   "source": [
    "### Option type"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "40a25756-5961-4f61-9106-5d664ddf3110",
   "metadata": {},
   "source": [
    "- A type that can hold a value of type `T`, or be undefined\n",
    "\n",
    "```\n",
    "enum Option<T> {\n",
    "    None,\n",
    "    Some(T),\n",
    "}\n",
    "```\n",
    "- Like `Maybe` in Haskell"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b9a811f6-7d08-401a-a8cf-f3a3e56dcd80",
   "metadata": {},
   "source": [
    "- Examples (`Option` is a built-in enum)\n",
    "- Note that `None` has to be explicitly typed"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "f2abffcf-d325-4565-8236-609988444bac",
   "metadata": {},
   "outputs": [],
   "source": [
    "let some_number = Some(5);\n",
    "let some_char = Some('e');"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a34e863c-b821-4c9a-84e1-047eb441566d",
   "metadata": {},
   "outputs": [
    {
     "ename": "Error",
     "evalue": "type annotations needed for `Option<_>`",
     "output_type": "error",
     "traceback": [
      "\u001b[31m[E0282] Error:\u001b[0m type annotations needed for `Option<_>`",
      "   \u001b[38;5;246m╭\u001b[0m\u001b[38;5;246m─\u001b[0m\u001b[38;5;246m[\u001b[0mcommand_16:1:1\u001b[38;5;246m]\u001b[0m",
      "   \u001b[38;5;246m│\u001b[0m",
      " \u001b[38;5;246m1 │\u001b[0m \u001b[38;5;249ml\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;100ma\u001b[0m\u001b[38;5;100mb\u001b[0m\u001b[38;5;100ms\u001b[0m\u001b[38;5;100me\u001b[0m\u001b[38;5;100mn\u001b[0m\u001b[38;5;100mt\u001b[0m\u001b[38;5;100m_\u001b[0m\u001b[38;5;100mn\u001b[0m\u001b[38;5;100mu\u001b[0m\u001b[38;5;100mm\u001b[0m\u001b[38;5;100mb\u001b[0m\u001b[38;5;100me\u001b[0m\u001b[38;5;100mr\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m=\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;54mN\u001b[0m\u001b[38;5;54mo\u001b[0m\u001b[38;5;54mn\u001b[0m\u001b[38;5;54me\u001b[0m\u001b[38;5;249m;\u001b[0m",
      " \u001b[38;5;240m  │\u001b[0m     \u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m┬\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;68m│\u001b[0m  \u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m┬\u001b[0m\u001b[38;5;54m─\u001b[0m  ",
      " \u001b[38;5;240m  │\u001b[0m           \u001b[38;5;100m╰\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m error: type annotations needed for `Option<_>`",
      " \u001b[38;5;240m  │\u001b[0m                  \u001b[38;5;68m│\u001b[0m    \u001b[38;5;54m│\u001b[0m   ",
      " \u001b[38;5;240m  │\u001b[0m                  \u001b[38;5;68m╰\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m help: consider giving `absent_number` an explicit type, where the type for type parameter `T` is specified: `: Option<T>`",
      " \u001b[38;5;240m  │\u001b[0m                       \u001b[38;5;54m│\u001b[0m   ",
      " \u001b[38;5;240m  │\u001b[0m                       \u001b[38;5;54m╰\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m type must be known at this point",
      "\u001b[38;5;246m───╯\u001b[0m"
     ]
    }
   ],
   "source": [
    "let absent_number = None;"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "6575aace-6588-46ff-992c-6fb7d53330b6",
   "metadata": {},
   "outputs": [],
   "source": [
    "let absent_number: Option<i32> = None;"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "51d86b97-8056-4024-ba04-4c6c8f32973e",
   "metadata": {},
   "source": [
    "- Can't mix `T` and `Some(T)` in an expression"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "04a21d18-f35b-4e9b-8433-47337c3bcda3",
   "metadata": {},
   "outputs": [
    {
     "ename": "Error",
     "evalue": "consider importing this trait",
     "output_type": "error",
     "traceback": [
      "\u001b[31mError:\u001b[0m consider importing this trait"
     ]
    },
    {
     "ename": "Error",
     "evalue": "cannot add `Option<i8>` to `i8`",
     "output_type": "error",
     "traceback": [
      "\u001b[31m[E0277] Error:\u001b[0m cannot add `Option<i8>` to `i8`",
      "   \u001b[38;5;246m╭\u001b[0m\u001b[38;5;246m─\u001b[0m\u001b[38;5;246m[\u001b[0mcommand_18:1:1\u001b[38;5;246m]\u001b[0m",
      "   \u001b[38;5;246m│\u001b[0m",
      " \u001b[38;5;246m4 │\u001b[0m \u001b[38;5;249ml\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249ms\u001b[0m\u001b[38;5;249mu\u001b[0m\u001b[38;5;249mm\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m=\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mx\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;54m+\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249my\u001b[0m\u001b[38;5;249m;\u001b[0m",
      " \u001b[38;5;240m  │\u001b[0m             \u001b[38;5;54m┬\u001b[0m  ",
      " \u001b[38;5;240m  │\u001b[0m             \u001b[38;5;54m╰\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m no implementation for `i8 + Option<i8>`",
      "\u001b[38;5;246m───╯\u001b[0m"
     ]
    }
   ],
   "source": [
    "let x: i8 = 5;\n",
    "let y: Option<i8> = Some(5);\n",
    "\n",
    "let sum = x + y;\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "680c3e22-7ad2-445e-ba08-bf9f8430c290",
   "metadata": {},
   "source": [
    "- Need to `unwrap()` the inner value from `Some(T)`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "86bff8d4-ffa0-4c41-9ff4-e3e72d73dc9d",
   "metadata": {},
   "outputs": [],
   "source": [
    "let x: i8 = 5;\n",
    "let y: Option<i8> = Some(5);\n",
    "\n",
    "let sum = x + y.unwrap();\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "0c504c0e-643a-4417-9b59-095592ce8309",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Some(5)"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "d0b9fc9a-3fdc-436b-b0bb-5b9bd1911aab",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y.unwrap()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5b44947d-54f6-45aa-a6a2-51d3e8ec4eb8",
   "metadata": {},
   "source": [
    "- Unwrapping `None` is an error"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "489a2d54-4eb8-4b8f-ac10-7b65efeb19a5",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n",
      "thread '<unnamed>' (486057) panicked at src/lib.rs:158:15:\n",
      "called `Option::unwrap()` on a `None` value\n",
      "stack backtrace:\n",
      "   0: __rustc::rust_begin_unwind\n",
      "             at /rustc/254b59607d4417e9dffbc307138ae5c86280fe4c/library/std/src/panicking.rs:689:5\n",
      "   1: core::panicking::panic_fmt\n",
      "             at /rustc/254b59607d4417e9dffbc307138ae5c86280fe4c/library/core/src/panicking.rs:80:14\n",
      "   2: core::panicking::panic\n",
      "             at /rustc/254b59607d4417e9dffbc307138ae5c86280fe4c/library/core/src/panicking.rs:150:5\n",
      "   3: core::option::unwrap_failed\n",
      "             at /rustc/254b59607d4417e9dffbc307138ae5c86280fe4c/library/core/src/option.rs:2175:5\n",
      "   4: run_user_code_18\n",
      "   5: evcxr::runtime::Runtime::run_loop\n",
      "   6: evcxr::runtime::runtime_hook\n",
      "   7: evcxr_jupyter::main\n",
      "note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.\n"
     ]
    }
   ],
   "source": [
    "absent_number.unwrap()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "84f726db-f73b-4ad5-836a-75e431fafe7a",
   "metadata": {},
   "source": [
    "### Matching"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c7f839f4-c97b-4c54-bbd6-149e960be847",
   "metadata": {},
   "source": [
    "- `match` operator selects amongst optional values in an `enum`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "4e562cad-be29-46e4-ab7b-7018ae12ca7d",
   "metadata": {},
   "outputs": [],
   "source": [
    "enum Coin {\n",
    "    Penny,\n",
    "    Nickel,\n",
    "    Dime,\n",
    "    Quarter,\n",
    "}\n",
    "\n",
    "fn value_in_cents(coin: Coin) -> u8 {\n",
    "    match coin {\n",
    "        Coin::Penny => {\n",
    "            println!(\"Lucky penny!\");\n",
    "            1\n",
    "        }\n",
    "        Coin::Nickel => 5,\n",
    "        Coin::Dime => 10,\n",
    "        Coin::Quarter => 25,\n",
    "    }\n",
    "}\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "ceb61591-f36d-4b43-9e05-848d31a10154",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Lucky penny!\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "let c = Coin::Penny;\n",
    "value_in_cents(c)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "6bf1d6f7-f795-43c1-8c65-b4f2a4e2be3e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "25"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "let c = Coin::Quarter;\n",
    "value_in_cents(c)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4f70f65b-76fb-4156-9932-ba12f00d6467",
   "metadata": {},
   "source": [
    "- `match` must return a consistent type"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d5d38c90-5645-4a75-9dbd-76c755d4fafb",
   "metadata": {},
   "outputs": [
    {
     "ename": "Error",
     "evalue": "`match` arms have incompatible types",
     "output_type": "error",
     "traceback": [
      "\u001b[31m[E0308] Error:\u001b[0m `match` arms have incompatible types",
      "   \u001b[38;5;246m╭\u001b[0m\u001b[38;5;246m─\u001b[0m\u001b[38;5;246m[\u001b[0mcommand_26:1:1\u001b[38;5;246m]\u001b[0m",
      "   \u001b[38;5;246m│\u001b[0m",
      " \u001b[38;5;246m1 │\u001b[0m \u001b[38;5;68m╭\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m▶\u001b[0m\u001b[38;5;68m \u001b[0m\u001b[38;5;249ml\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mz\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m=\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;68mm\u001b[0m\u001b[38;5;68ma\u001b[0m\u001b[38;5;68mt\u001b[0m\u001b[38;5;68mc\u001b[0m\u001b[38;5;68mh\u001b[0m\u001b[38;5;68m \u001b[0m\u001b[38;5;68my\u001b[0m\u001b[38;5;68m \u001b[0m\u001b[38;5;68m{\u001b[0m",
      " \u001b[38;5;246m2 │\u001b[0m \u001b[38;5;68m│\u001b[0m   \u001b[38;5;68m \u001b[0m\u001b[38;5;68m \u001b[0m\u001b[38;5;68m \u001b[0m\u001b[38;5;68m \u001b[0m\u001b[38;5;68mN\u001b[0m\u001b[38;5;68mo\u001b[0m\u001b[38;5;68mn\u001b[0m\u001b[38;5;68me\u001b[0m\u001b[38;5;68m \u001b[0m\u001b[38;5;68m=\u001b[0m\u001b[38;5;68m>\u001b[0m\u001b[38;5;68m \u001b[0m\u001b[38;5;100mN\u001b[0m\u001b[38;5;100mo\u001b[0m\u001b[38;5;100mn\u001b[0m\u001b[38;5;100me\u001b[0m\u001b[38;5;68m,\u001b[0m",
      " \u001b[38;5;240m  │\u001b[0m \u001b[38;5;68m│\u001b[0m               \u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m┬\u001b[0m\u001b[38;5;100m─\u001b[0m  ",
      " \u001b[38;5;240m  │\u001b[0m \u001b[38;5;68m│\u001b[0m                 \u001b[38;5;100m╰\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m this is found to be of type `Option<_>`",
      " \u001b[38;5;246m3 │\u001b[0m \u001b[38;5;68m│\u001b[0m   \u001b[38;5;68m \u001b[0m\u001b[38;5;68m \u001b[0m\u001b[38;5;68m \u001b[0m\u001b[38;5;68m \u001b[0m\u001b[38;5;68mS\u001b[0m\u001b[38;5;68mo\u001b[0m\u001b[38;5;68mm\u001b[0m\u001b[38;5;68me\u001b[0m\u001b[38;5;68m(\u001b[0m\u001b[38;5;68mx\u001b[0m\u001b[38;5;68m)\u001b[0m\u001b[38;5;68m \u001b[0m\u001b[38;5;68m=\u001b[0m\u001b[38;5;68m>\u001b[0m\u001b[38;5;68m \u001b[0m\u001b[38;5;54my\u001b[0m\u001b[38;5;54m.\u001b[0m\u001b[38;5;54mu\u001b[0m\u001b[38;5;54mn\u001b[0m\u001b[38;5;54mw\u001b[0m\u001b[38;5;54mr\u001b[0m\u001b[38;5;54ma\u001b[0m\u001b[38;5;54mp\u001b[0m\u001b[38;5;54m(\u001b[0m\u001b[38;5;54m)\u001b[0m\u001b[38;5;68m,\u001b[0m",
      " \u001b[38;5;240m  │\u001b[0m \u001b[38;5;68m│\u001b[0m                  \u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m┬\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m  ",
      " \u001b[38;5;240m  │\u001b[0m \u001b[38;5;68m│\u001b[0m                       \u001b[38;5;54m╰\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m expected `Option<_>`, found `i8`",
      " \u001b[38;5;246m4 │\u001b[0m \u001b[38;5;68m├\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m▶\u001b[0m\u001b[38;5;68m \u001b[0m\u001b[38;5;68m}\u001b[0m\u001b[38;5;249m;\u001b[0m",
      " \u001b[38;5;240m  │\u001b[0m \u001b[38;5;68m│\u001b[0m       ",
      " \u001b[38;5;240m  │\u001b[0m \u001b[38;5;68m╰\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m `match` arms have incompatible types",
      "\u001b[38;5;246m───╯\u001b[0m"
     ]
    }
   ],
   "source": [
    "let z = match y {\n",
    "    None => None,\n",
    "    Some(x) => y.unwrap(),\n",
    "};"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9221c63f-e44f-41a0-aa1a-5ade39fa9c48",
   "metadata": {},
   "source": [
    "- This works"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "ca85f45e-1ff9-44db-95e3-cfb67d80b3d0",
   "metadata": {},
   "outputs": [],
   "source": [
    "fn plus_one(x: Option<i32>) -> Option<i32> {\n",
    "    match x {\n",
    "        None => None,\n",
    "        Some(i) => Some(i + 1),\n",
    "    }\n",
    "}\n",
    "\n",
    "let five = Some(5);\n",
    "let six = plus_one(five);\n",
    "let none = plus_one(None);\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "09a20cd1-d460-4095-bd7c-a5f14a78dca3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Some(5)"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "five"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "b9b977c3-ac22-408d-8ec5-ed563f67d3e0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Some(6)"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "six"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "9da1c825-d849-4ef5-be97-ec25c33e7ba0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "None"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "none"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ed182ec7-b2db-4d2c-a6e5-3bb0a334c17f",
   "metadata": {},
   "source": [
    "- Can pattern match and operate within an enum\n",
    "- **All** possible values must be covered -- error tells you which value was missed\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ff0587e2-a804-4866-a7e9-1cc405eff091",
   "metadata": {},
   "outputs": [
    {
     "ename": "Error",
     "evalue": "non-exhaustive patterns: `None` not covered",
     "output_type": "error",
     "traceback": [
      "\u001b[31m[E0004] Error:\u001b[0m non-exhaustive patterns: `None` not covered",
      "   \u001b[38;5;246m╭\u001b[0m\u001b[38;5;246m─\u001b[0m\u001b[38;5;246m[\u001b[0mcommand_31:1:1\u001b[38;5;246m]\u001b[0m",
      "   \u001b[38;5;246m│\u001b[0m",
      " \u001b[38;5;246m2 │\u001b[0m \u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mm\u001b[0m\u001b[38;5;249ma\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249mc\u001b[0m\u001b[38;5;249mh\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;54mx\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m{\u001b[0m",
      " \u001b[38;5;240m  │\u001b[0m           \u001b[38;5;54m┬\u001b[0m  ",
      " \u001b[38;5;240m  │\u001b[0m           \u001b[38;5;54m╰\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m pattern `None` not covered",
      " \u001b[38;5;246m3 │\u001b[0m \u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mS\u001b[0m\u001b[38;5;249mo\u001b[0m\u001b[38;5;249mm\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249m(\u001b[0m\u001b[38;5;249mi\u001b[0m\u001b[38;5;249m)\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m=\u001b[0m\u001b[38;5;249m>\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mS\u001b[0m\u001b[38;5;249mo\u001b[0m\u001b[38;5;249mm\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249m(\u001b[0m\u001b[38;5;249mi\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m+\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m1\u001b[0m\u001b[38;5;249m)\u001b[0m\u001b[38;5;249m,\u001b[0m",
      " \u001b[38;5;240m  │\u001b[0m                               \u001b[38;5;100m│\u001b[0m ",
      " \u001b[38;5;240m  │\u001b[0m                               \u001b[38;5;100m╰\u001b[0m\u001b[38;5;100m─\u001b[0m help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown: `,",
      "        None => todo!()`",
      "\u001b[38;5;246m───╯\u001b[0m"
     ]
    }
   ],
   "source": [
    "fn plus_one(x: Option<i32>) -> Option<i32> {\n",
    "    match x {\n",
    "        Some(i) => Some(i + 1),\n",
    "    }\n",
    "}\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "7e0b6264-4a9d-42f0-92cf-5e0f7f06f911",
   "metadata": {},
   "outputs": [],
   "source": [
    "fn plus_one(x: Option<i32>) -> Option<i32> {\n",
    "    match x {\n",
    "        None => None,\n",
    "        Some(i) => Some(i + 1),\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9c6010bb-b0b8-4f56-9679-af28d32aeaa1",
   "metadata": {},
   "source": [
    "- `match` is not restricted to finite number of options\n",
    "- `other` is a catch-all pattern (`other` is not a keyword, can use any label)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "da3ecd46-5a4a-4ef7-94dd-2899ccea0d58",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Add fancy hat\n"
     ]
    }
   ],
   "source": [
    "let dice_roll = 3;\n",
    "match dice_roll {\n",
    "    3 => add_fancy_hat(),\n",
    "    7 => remove_fancy_hat(),\n",
    "    other => move_player(other),\n",
    "}\n",
    "\n",
    "fn add_fancy_hat() {println!(\"Add fancy hat\");}\n",
    "fn remove_fancy_hat() {println!(\"Remove fancy hat\");}\n",
    "fn move_player(num_spaces: u8) {println!(\"Move {} spaces\",num_spaces);}\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "4cce6399-4ff9-4cf8-9a52-42fe11e73e65",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Remove fancy hat\n"
     ]
    }
   ],
   "source": [
    "let dice_roll = 7;\n",
    "match dice_roll {\n",
    "    3 => add_fancy_hat(),\n",
    "    7 => remove_fancy_hat(),\n",
    "    other => move_player(other),\n",
    "}\n",
    "\n",
    "fn add_fancy_hat() {println!(\"Add fancy hat\");}\n",
    "fn remove_fancy_hat() {println!(\"Remove fancy hat\");}\n",
    "fn move_player(num_spaces: u8) {println!(\"Move {} spaces\",num_spaces);}\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "12948936-ae14-4621-b328-4aa001ac84ac",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Move 9 spaces\n"
     ]
    }
   ],
   "source": [
    "let dice_roll = 9;\n",
    "match dice_roll {\n",
    "    3 => add_fancy_hat(),\n",
    "    7 => remove_fancy_hat(),\n",
    "    other => move_player(other),\n",
    "}\n",
    "\n",
    "fn add_fancy_hat() {println!(\"Add fancy hat\");}\n",
    "fn remove_fancy_hat() {println!(\"Remove fancy hat\");}\n",
    "fn move_player(num_spaces: u8) {println!(\"Move {} spaces\",num_spaces);}\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2a187139-c12a-407f-8d53-4620bac50561",
   "metadata": {},
   "source": [
    "- If we don't need the value, can use anonymous `_` instead of a label\n",
    "  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "c92e636c-6146-46ea-aad8-d1b00c1ea692",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Reroll\n"
     ]
    }
   ],
   "source": [
    "let dice_roll = 9;\n",
    "match dice_roll {\n",
    "    3 => add_fancy_hat(),\n",
    "    7 => remove_fancy_hat(),\n",
    "    _ => reroll(),\n",
    "}\n",
    "\n",
    "fn add_fancy_hat() {println!(\"Add fancy hat\");}\n",
    "fn remove_fancy_hat() {println!(\"Remove fancy hat\");}\n",
    "fn reroll() {println!(\"Reroll\");}\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "69e52a75-bffa-4b32-8566-9b81875aea6d",
   "metadata": {},
   "source": [
    "### Panic"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d844d62c-a24f-4c49-b4b0-80f912f9a243",
   "metadata": {},
   "source": [
    "- Rust \"panics\" when it encounters an unrecoverable error at run-time, such as an index out of bounds"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "a5d55b7b-7a35-4c05-8248-fd949493e4a4",
   "metadata": {},
   "outputs": [],
   "source": [
    "fn main() {\n",
    "    let v = vec![1, 2, 3];\n",
    "\n",
    "    v[99];\n",
    "}\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "5a81977b-6f78-418e-a44a-5de9a498c7b0",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n",
      "thread '<unnamed>' (486057) panicked at src/lib.rs:60:6:\n",
      "index out of bounds: the len is 3 but the index is 99\n",
      "stack backtrace:\n",
      "   0: __rustc::rust_begin_unwind\n",
      "             at /rustc/254b59607d4417e9dffbc307138ae5c86280fe4c/library/std/src/panicking.rs:689:5\n",
      "   1: core::panicking::panic_fmt\n",
      "             at /rustc/254b59607d4417e9dffbc307138ae5c86280fe4c/library/core/src/panicking.rs:80:14\n",
      "   2: core::panicking::panic_bounds_check\n",
      "             at /rustc/254b59607d4417e9dffbc307138ae5c86280fe4c/library/core/src/panicking.rs:271:5\n",
      "   3: <unknown>\n",
      "   4: <unknown>\n",
      "   5: <unknown>\n",
      "   6: evcxr::runtime::Runtime::run_loop\n",
      "   7: evcxr::runtime::runtime_hook\n",
      "   8: evcxr_jupyter::main\n",
      "note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.\n"
     ]
    }
   ],
   "source": [
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "50871585-6668-4b3e-8659-c5f54b464abb",
   "metadata": {},
   "source": [
    "- Observe what happens if we use an array instead of a vector\n",
    "- Rust is able to catch the potential panic at compile time!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "402c0526-6e7f-42c8-9bb6-2c1b15043445",
   "metadata": {},
   "outputs": [
    {
     "ename": "Error",
     "evalue": "this operation will panic at runtime",
     "output_type": "error",
     "traceback": [
      "\u001b[31m[unconditional_panic] Error:\u001b[0m this operation will panic at runtime",
      "   \u001b[38;5;246m╭\u001b[0m\u001b[38;5;246m─\u001b[0m\u001b[38;5;246m[\u001b[0mcommand_39:1:1\u001b[38;5;246m]\u001b[0m",
      "   \u001b[38;5;246m│\u001b[0m",
      " \u001b[38;5;246m4 │\u001b[0m \u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;54mv\u001b[0m\u001b[38;5;54m[\u001b[0m\u001b[38;5;54m9\u001b[0m\u001b[38;5;54m9\u001b[0m\u001b[38;5;54m]\u001b[0m\u001b[38;5;249m;\u001b[0m",
      " \u001b[38;5;240m  │\u001b[0m     \u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m┬\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m  ",
      " \u001b[38;5;240m  │\u001b[0m       \u001b[38;5;54m╰\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m index out of bounds: the length is 3 but the index is 99",
      "\u001b[38;5;246m───╯\u001b[0m"
     ]
    }
   ],
   "source": [
    "fn main() {\n",
    "    let v = [1, 2, 3];\n",
    "\n",
    "    v[99];\n",
    "}\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "840aff90-9549-47c5-9314-14cc12386002",
   "metadata": {},
   "source": [
    "- However, if we obfuscate the array access, we achieve a run-time panic"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "65325c82-3868-4b91-b99e-aca8aa230500",
   "metadata": {},
   "outputs": [],
   "source": [
    "fn check(x:usize) {\n",
    "    let v = [1, 2, 3];\n",
    "\n",
    "    v[x];\n",
    "}\n",
    "\n",
    "fn main(){\n",
    "    let x:usize = 22;\n",
    "    check(x)\n",
    "}\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "df4d9fa1-17eb-49a7-be41-3fb6bf916c00",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n",
      "thread '<unnamed>' (486057) panicked at src/lib.rs:64:5:\n",
      "index out of bounds: the len is 3 but the index is 22\n",
      "stack backtrace:\n",
      "   0: __rustc::rust_begin_unwind\n",
      "             at /rustc/254b59607d4417e9dffbc307138ae5c86280fe4c/library/std/src/panicking.rs:689:5\n",
      "   1: core::panicking::panic_fmt\n",
      "             at /rustc/254b59607d4417e9dffbc307138ae5c86280fe4c/library/core/src/panicking.rs:80:14\n",
      "   2: core::panicking::panic_bounds_check\n",
      "             at /rustc/254b59607d4417e9dffbc307138ae5c86280fe4c/library/core/src/panicking.rs:271:5\n",
      "   3: <unknown>\n",
      "   4: <unknown>\n",
      "   5: evcxr::runtime::Runtime::run_loop\n",
      "   6: evcxr::runtime::runtime_hook\n",
      "   7: evcxr_jupyter::main\n",
      "note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.\n"
     ]
    }
   ],
   "source": [
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "875f7b8b-2d6a-4917-af61-2bfb58b1e3b6",
   "metadata": {},
   "source": [
    "- We can directly invoke `panic()` with an error message\n",
    "- Useful if code detects an unrecoverable situation and wants to abort"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "189f4b61-50b8-4a87-810b-403f45b2895d",
   "metadata": {},
   "outputs": [],
   "source": [
    "fn main() {\n",
    "    panic!(\"Crash and burn!\");\n",
    "}\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "40bf8318-d4e5-4af5-9987-38b99261f228",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n",
      "thread '<unnamed>' (486057) panicked at src/lib.rs:58:5:\n",
      "Crash and burn!\n",
      "stack backtrace:\n",
      "   0: __rustc::rust_begin_unwind\n",
      "             at /rustc/254b59607d4417e9dffbc307138ae5c86280fe4c/library/std/src/panicking.rs:689:5\n",
      "   1: core::panicking::panic_fmt\n",
      "             at /rustc/254b59607d4417e9dffbc307138ae5c86280fe4c/library/core/src/panicking.rs:80:14\n",
      "   2: <unknown>\n",
      "   3: <unknown>\n",
      "   4: evcxr::runtime::Runtime::run_loop\n",
      "   5: evcxr::runtime::runtime_hook\n",
      "   6: evcxr_jupyter::main\n",
      "note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.\n"
     ]
    }
   ],
   "source": [
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ea54d0ed-644e-4b86-ab72-7317a400512c",
   "metadata": {},
   "source": [
    "### Result\n",
    "- An enum to return informative error messages\n",
    "```\n",
    "enum Result<T, E> {\n",
    "    Ok(T),\n",
    "    Err(E),\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bdfc43c4-8ddc-44d3-9138-8436c61395a8",
   "metadata": {},
   "source": [
    "- This code generates an error if `hello.txt` is not found in the current directory\n",
    "- If the file can be opened, returns file handle for `hello.txt`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "d5a3c7f1-427d-410b-a70e-8b5b41342c8a",
   "metadata": {},
   "outputs": [],
   "source": [
    "use std::fs::File;\n",
    "\n",
    "fn main() {\n",
    "    let greeting_file_result = File::open(\"hello.txt\");\n",
    "\n",
    "    let greeting_file = match greeting_file_result {\n",
    "        Ok(file) => file,\n",
    "        Err(error) => panic!(\"Problem opening the file: {:?}\", error),\n",
    "    };\n",
    "}\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "f920bab6-37d2-4123-a5a6-25aa928155ed",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n",
      "thread '<unnamed>' (486057) panicked at src/lib.rs:63:23:\n",
      "Problem opening the file: Os { code: 2, kind: NotFound, message: \"No such file or directory\" }\n",
      "stack backtrace:\n",
      "   0: __rustc::rust_begin_unwind\n",
      "             at /rustc/254b59607d4417e9dffbc307138ae5c86280fe4c/library/std/src/panicking.rs:689:5\n",
      "   1: core::panicking::panic_fmt\n",
      "             at /rustc/254b59607d4417e9dffbc307138ae5c86280fe4c/library/core/src/panicking.rs:80:14\n",
      "   2: <unknown>\n",
      "   3: evcxr::runtime::Runtime::run_loop\n",
      "   4: evcxr::runtime::runtime_hook\n",
      "   5: evcxr_jupyter::main\n",
      "note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.\n"
     ]
    }
   ],
   "source": [
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "12e8b35d-8924-4ea6-ac04-53f0723bd345",
   "metadata": {},
   "source": [
    "- [Created `hello.txt`]\n",
    "- Here is what happens if `hello.txt` opens fine"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "551979b4-f529-411c-ba5e-27223543ae28",
   "metadata": {},
   "outputs": [],
   "source": [
    "use std::fs::File;\n",
    "\n",
    "fn main() {\n",
    "    let greeting_file_result = File::open(\"hello.txt\");\n",
    "\n",
    "    let greeting_file = match greeting_file_result {\n",
    "        Ok(file) => {println!(\"Opened hello.txt\"); file},\n",
    "        Err(error) => panic!(\"Problem opening the file: {:?}\", error),\n",
    "    };\n",
    "}\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "daa44008-4828-490d-b4df-803ab66346ca",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Opened hello.txt\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c2a50c82-b99b-45c7-b0b8-2b91175c7f46",
   "metadata": {},
   "source": [
    "- [Deleted `hello.txt`]\n",
    "- Can `match` on type of error\n",
    "- Can have nested (chained) errors"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "8e647e80-2df0-456e-b2a3-f45a88f656ce",
   "metadata": {},
   "outputs": [],
   "source": [
    "use std::fs::File;\n",
    "use std::io::ErrorKind;\n",
    "\n",
    "fn main() {\n",
    "    let greeting_file_result = File::open(\"hello.txt\");\n",
    "\n",
    "    let greeting_file = match greeting_file_result {\n",
    "        Ok(file) => file,\n",
    "        Err(error) => match error.kind() {\n",
    "            ErrorKind::NotFound => match File::create(\"hello.txt\") {\n",
    "                Ok(fc) => {println!(\"Created file!\"); fc},\n",
    "                Err(e) => panic!(\"Problem creating the file: {:?}\", e),\n",
    "            },\n",
    "            other_error => {\n",
    "                panic!(\"Problem opening the file: {:?}\", other_error);\n",
    "            }\n",
    "        },\n",
    "    };\n",
    "}\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "78609373-c05a-49b9-9a28-7f8a749b9a60",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Created file!\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2c160d27-0b62-4f87-ab34-d6cf62777797",
   "metadata": {},
   "source": [
    "- [Deleted `hello.txt`]\n",
    "- Shortcut: `unwrap()` extracts the match for the `OK` branch"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "id": "0a311f5d-10c2-4f54-b97e-47f6122705b9",
   "metadata": {},
   "outputs": [],
   "source": [
    "use std::fs::File;\n",
    "\n",
    "fn main() {\n",
    "    let greeting_file = File::open(\"hello.txt\").unwrap();\n",
    "}\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "id": "2f94c81b-448a-4e17-a480-b03ebaf8eb54",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n",
      "thread '<unnamed>' (486057) panicked at src/lib.rs:58:49:\n",
      "called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: \"No such file or directory\" }\n",
      "stack backtrace:\n",
      "   0: __rustc::rust_begin_unwind\n",
      "             at /rustc/254b59607d4417e9dffbc307138ae5c86280fe4c/library/std/src/panicking.rs:689:5\n",
      "   1: core::panicking::panic_fmt\n",
      "             at /rustc/254b59607d4417e9dffbc307138ae5c86280fe4c/library/core/src/panicking.rs:80:14\n",
      "   2: core::result::unwrap_failed\n",
      "             at /rustc/254b59607d4417e9dffbc307138ae5c86280fe4c/library/core/src/result.rs:1867:5\n",
      "   3: <unknown>\n",
      "   4: evcxr::runtime::Runtime::run_loop\n",
      "   5: evcxr::runtime::runtime_hook\n",
      "   6: evcxr_jupyter::main\n",
      "note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.\n"
     ]
    }
   ],
   "source": [
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1fdf6282-365e-4786-8f65-7aa755698d4c",
   "metadata": {},
   "source": [
    "- `expect()` is triggered by the `Err` branch and panics with a message\n",
    "- If no error, `unwrap()` is invoked implicitly, see later"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "7b1c7c67-2320-48a6-8a26-63db87aee4e1",
   "metadata": {},
   "outputs": [],
   "source": [
    "use std::fs::File;\n",
    "\n",
    "fn main() {\n",
    "    let greeting_file = File::open(\"hello.txt\")\n",
    "        .expect(\"hello.txt should be included in this project\");\n",
    "}\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "29f3a816-37b7-4fb7-809f-a9b9b12b4a91",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n",
      "thread '<unnamed>' (486057) panicked at src/lib.rs:59:10:\n",
      "hello.txt should be included in this project: Os { code: 2, kind: NotFound, message: \"No such file or directory\" }\n",
      "stack backtrace:\n",
      "   0: __rustc::rust_begin_unwind\n",
      "             at /rustc/254b59607d4417e9dffbc307138ae5c86280fe4c/library/std/src/panicking.rs:689:5\n",
      "   1: core::panicking::panic_fmt\n",
      "             at /rustc/254b59607d4417e9dffbc307138ae5c86280fe4c/library/core/src/panicking.rs:80:14\n",
      "   2: core::result::unwrap_failed\n",
      "             at /rustc/254b59607d4417e9dffbc307138ae5c86280fe4c/library/core/src/result.rs:1867:5\n",
      "   3: <unknown>\n",
      "   4: evcxr::runtime::Runtime::run_loop\n",
      "   5: evcxr::runtime::runtime_hook\n",
      "   6: evcxr_jupyter::main\n",
      "note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.\n"
     ]
    }
   ],
   "source": [
    "main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7ec6696f-994a-4cd5-921e-3c0ff97240f2",
   "metadata": {},
   "source": [
    "### Propagating errors\n",
    "- The code below first tries to open `hello.txt`\n",
    "- If this succeeds, it tries to read `username` from the file\n",
    "- If either the file open or the file read fails, `Err(e)` is propagated to caller\n",
    "  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "id": "d9d03bab-7753-4df8-b0f1-f65b78b7a931",
   "metadata": {},
   "outputs": [],
   "source": [
    "use std::fs::File;\n",
    "use std::io::{self, Read};\n",
    "\n",
    "fn read_username_from_file() -> Result<String, io::Error> {\n",
    "    let username_file_result = File::open(\"hello.txt\");\n",
    "\n",
    "    let mut username_file = match username_file_result {\n",
    "        Ok(file) => file,\n",
    "        Err(e) => return Err(e),\n",
    "    };\n",
    "\n",
    "    let mut username = String::new();\n",
    "\n",
    "    match username_file.read_to_string(&mut username) {\n",
    "        Ok(_) => Ok(username),\n",
    "        Err(e) => Err(e),\n",
    "    }\n",
    "}\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "475b6a16-78f7-4cbb-bd92-518d070dddee",
   "metadata": {},
   "source": [
    "- [Created `hello.txt` with contents `\"Hello world\"`]\n",
    "- The example above, without an error\n",
    "- `expect()` implicitly invokes `unwrap()` and file handle is stored in `greeting_file`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "id": "7fae08fc-e0ff-406f-873b-f8042acffd96",
   "metadata": {},
   "outputs": [],
   "source": [
    "use std::fs::File;\n",
    "use std::io::{self, Read};\n",
    "\n",
    "fn main() {\n",
    "    let mut greeting_file = File::open(\"hello.txt\")\n",
    "        .expect(\"hello.txt should be included in this project\");\n",
    "\n",
    "    let mut username = String::new();\n",
    "\n",
    "    greeting_file.read_to_string(&mut username);\n",
    "\n",
    "    println!(\"{}\",username);\n",
    "    \n",
    "}\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "id": "2cdd9c50-118e-490b-b1e0-57a7cfebd098",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello world\n",
      "\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "main()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Rust",
   "language": "rust",
   "name": "rust"
  },
  "language_info": {
   "codemirror_mode": "rust",
   "file_extension": ".rs",
   "mimetype": "text/rust",
   "name": "Rust",
   "pygment_lexer": "rust",
   "version": ""
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
