diff --git a/f23/Gurmail_Lecture_Notes/23_Function_References/lec_23_function_references.ipynb b/f23/Gurmail_Lecture_Notes/23_Function_References/lec_23_function_references.ipynb
index 43b5e6bd9558d6e5e3f301d362462df0f1d96e1d..8139c7021c55d885332eac97cffb5270d63f0613 100644
--- a/f23/Gurmail_Lecture_Notes/23_Function_References/lec_23_function_references.ipynb
+++ b/f23/Gurmail_Lecture_Notes/23_Function_References/lec_23_function_references.ipynb
@@ -1,5 +1,21 @@
 {
  "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# Announcements - Monday, October 30\n",
+    "\n",
+    "* Download ALL files for today's lecture\n",
+    "* <b>If you have any problem with P1-P4 grades, please send me (Gurmail.Singh@wisc.edu) an email by November 03.</b>\n",
+    "* If you have questions, it is almost always faster to \n",
+    "  * Post on Piazza\n",
+    "  * Go to [office hours](https://sites.google.com/wisc.edu/cs220-oh-f23/home?pli=1) \n",
+    "### Conflict Form\n",
+    "  * [Exam 2 - November 8, 5:45 pm](https://cs220.cs.wisc.edu/f23/surveys.html)\n",
+    "  * [Final - December 19, 7:45 am](https://cs220.cs.wisc.edu/f23/surveys.html)"
+   ]
+  },
   {
    "cell_type": "markdown",
    "metadata": {},
@@ -19,6 +35,39 @@
    "execution_count": 1,
    "metadata": {},
    "outputs": [],
+   "source": [
+    "def fact(n):\n",
+    "    if n == 1:\n",
+    "        return 1\n",
+    "    p = fact(n-1)                                   \n",
+    "    return n * p"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "6"
+      ]
+     },
+     "execution_count": 2,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "fact(3)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "metadata": {},
+   "outputs": [],
    "source": [
     "# Nested data structures are defined recursively.\n",
     "\n",
@@ -29,7 +78,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 2,
+   "execution_count": 4,
    "metadata": {},
    "outputs": [
     {
@@ -38,7 +87,7 @@
        "9"
       ]
      },
-     "execution_count": 2,
+     "execution_count": 4,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -100,7 +149,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 3,
+   "execution_count": 5,
    "metadata": {},
    "outputs": [
     {
@@ -138,7 +187,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 4,
+   "execution_count": 6,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -157,7 +206,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 5,
+   "execution_count": 7,
    "metadata": {},
    "outputs": [
     {
@@ -190,7 +239,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 6,
+   "execution_count": 8,
    "metadata": {},
    "outputs": [
     {
@@ -215,7 +264,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 7,
+   "execution_count": 9,
    "metadata": {},
    "outputs": [
     {
@@ -241,7 +290,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 8,
+   "execution_count": 10,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -261,7 +310,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 9,
+   "execution_count": 11,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -277,7 +326,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 10,
+   "execution_count": 12,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -311,7 +360,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 11,
+   "execution_count": 13,
    "metadata": {},
    "outputs": [
     {
@@ -320,7 +369,7 @@
        "[1, 23, 456]"
       ]
      },
-     "execution_count": 11,
+     "execution_count": 13,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -339,7 +388,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 12,
+   "execution_count": 14,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -368,7 +417,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 13,
+   "execution_count": 15,
    "metadata": {},
    "outputs": [
     {
@@ -397,7 +446,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 14,
+   "execution_count": 16,
    "metadata": {},
    "outputs": [
     {
@@ -434,7 +483,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 15,
+   "execution_count": 17,
    "metadata": {},
    "outputs": [
     {
@@ -447,7 +496,7 @@
        " ('Troy', 'Fumagalli', 88)]"
       ]
      },
-     "execution_count": 15,
+     "execution_count": 17,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -479,7 +528,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 16,
+   "execution_count": 18,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -495,7 +544,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 17,
+   "execution_count": 19,
    "metadata": {},
    "outputs": [
     {
@@ -504,7 +553,7 @@
        "'JJ'"
       ]
      },
-     "execution_count": 17,
+     "execution_count": 19,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -523,7 +572,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 18,
+   "execution_count": 20,
    "metadata": {},
    "outputs": [
     {
@@ -536,7 +585,7 @@
        " ('Russel', 'Wilson', 32)]"
       ]
      },
-     "execution_count": 18,
+     "execution_count": 20,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -554,7 +603,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 19,
+   "execution_count": 21,
    "metadata": {},
    "outputs": [
     {
@@ -567,7 +616,7 @@
        " ('Troy', 'Fumagalli', 88)]"
       ]
      },
-     "execution_count": 19,
+     "execution_count": 21,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -585,7 +634,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 20,
+   "execution_count": 22,
    "metadata": {},
    "outputs": [
     {
@@ -598,7 +647,7 @@
        " ('Jonathan', 'Taylor', 22)]"
       ]
      },
-     "execution_count": 20,
+     "execution_count": 22,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -616,7 +665,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 21,
+   "execution_count": 23,
    "metadata": {},
    "outputs": [
     {
@@ -629,7 +678,7 @@
        " ('Jonathan', 'Taylor', 22)]"
       ]
      },
-     "execution_count": 21,
+     "execution_count": 23,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -650,7 +699,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 22,
+   "execution_count": 24,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -670,7 +719,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 23,
+   "execution_count": 25,
    "metadata": {},
    "outputs": [
     {
@@ -679,7 +728,7 @@
        "{'name': 'A', 'year': 2000, 'speed': 150}"
       ]
      },
-     "execution_count": 23,
+     "execution_count": 25,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -697,7 +746,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 24,
+   "execution_count": 26,
    "metadata": {},
    "outputs": [
     {
@@ -706,7 +755,7 @@
        "{'name': 'B', 'year': 1980, 'speed': 100}"
       ]
      },
-     "execution_count": 24,
+     "execution_count": 26,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -724,7 +773,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 25,
+   "execution_count": 27,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -740,7 +789,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 26,
+   "execution_count": 28,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -757,7 +806,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 27,
+   "execution_count": 29,
    "metadata": {},
    "outputs": [
     {
@@ -777,7 +826,7 @@
        " {'name': 'A', 'year': 2000, 'speed': 150}]"
       ]
      },
-     "execution_count": 27,
+     "execution_count": 29,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -802,7 +851,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 28,
+   "execution_count": 30,
    "metadata": {},
    "outputs": [
     {
@@ -822,7 +871,7 @@
        " {'name': 'B', 'year': 1980, 'speed': 100}]"
       ]
      },
-     "execution_count": 28,
+     "execution_count": 30,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -842,7 +891,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 29,
+   "execution_count": 31,
    "metadata": {},
    "outputs": [
     {
@@ -853,7 +902,7 @@
        " {'name': 'A', 'year': 2000, 'speed': 150}]"
       ]
      },
-     "execution_count": 29,
+     "execution_count": 31,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -880,7 +929,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 30,
+   "execution_count": 32,
    "metadata": {},
    "outputs": [
     {
@@ -889,7 +938,7 @@
        "['A', 'C', 'b', 'd']"
       ]
      },
-     "execution_count": 30,
+     "execution_count": 32,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -900,7 +949,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 31,
+   "execution_count": 33,
    "metadata": {},
    "outputs": [
     {
@@ -909,7 +958,7 @@
        "['A', 'b', 'C', 'd']"
       ]
      },
-     "execution_count": 31,
+     "execution_count": 33,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -934,7 +983,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 32,
+   "execution_count": 34,
    "metadata": {},
    "outputs": [
     {
@@ -943,7 +992,7 @@
        "{'bob': 20, 'alice': 8, 'alex': 9, 'cindy': 15}"
       ]
      },
-     "execution_count": 32,
+     "execution_count": 34,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -966,7 +1015,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 33,
+   "execution_count": 35,
    "metadata": {},
    "outputs": [
     {
@@ -975,7 +1024,7 @@
        "['alex', 'alice', 'bob', 'cindy']"
       ]
      },
-     "execution_count": 33,
+     "execution_count": 35,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -995,7 +1044,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 34,
+   "execution_count": 36,
    "metadata": {},
    "outputs": [
     {
@@ -1004,7 +1053,7 @@
        "dict_items([('bob', 20), ('alice', 8), ('alex', 9), ('cindy', 15)])"
       ]
      },
-     "execution_count": 34,
+     "execution_count": 36,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -1022,7 +1071,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 35,
+   "execution_count": 37,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -1039,7 +1088,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 36,
+   "execution_count": 38,
    "metadata": {},
    "outputs": [
     {
@@ -1048,7 +1097,7 @@
        "[('alice', 8), ('alex', 9), ('cindy', 15), ('bob', 20)]"
       ]
      },
-     "execution_count": 36,
+     "execution_count": 38,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -1066,7 +1115,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 37,
+   "execution_count": 39,
    "metadata": {},
    "outputs": [
     {
@@ -1075,7 +1124,7 @@
        "{'alice': 8, 'alex': 9, 'cindy': 15, 'bob': 20}"
       ]
      },
-     "execution_count": 37,
+     "execution_count": 39,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -1112,7 +1161,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 38,
+   "execution_count": 40,
    "metadata": {},
    "outputs": [
     {
@@ -1121,7 +1170,7 @@
        "{'alex': 9, 'alice': 8, 'bob': 20, 'cindy': 15}"
       ]
      },
-     "execution_count": 38,
+     "execution_count": 40,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -1139,7 +1188,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 39,
+   "execution_count": 41,
    "metadata": {},
    "outputs": [
     {
@@ -1148,7 +1197,7 @@
        "{'alice': 8, 'alex': 9, 'cindy': 15, 'bob': 20}"
       ]
      },
-     "execution_count": 39,
+     "execution_count": 41,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -1166,7 +1215,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 40,
+   "execution_count": 42,
    "metadata": {},
    "outputs": [
     {
@@ -1175,7 +1224,7 @@
        "{'bob': 20, 'alex': 9, 'alice': 8, 'cindy': 15}"
       ]
      },
-     "execution_count": 40,
+     "execution_count": 42,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -1193,7 +1242,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 41,
+   "execution_count": 43,
    "metadata": {},
    "outputs": [
     {
@@ -1217,7 +1266,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 42,
+   "execution_count": 44,
    "metadata": {},
    "outputs": [
     {
@@ -1230,7 +1279,7 @@
        " ('Troy', 'Fumagalli', 88)]"
       ]
      },
-     "execution_count": 42,
+     "execution_count": 44,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -1248,7 +1297,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 43,
+   "execution_count": 45,
    "metadata": {},
    "outputs": [
     {
@@ -1261,7 +1310,7 @@
        " ('Russel', 'Wilson', 32)]"
       ]
      },
-     "execution_count": 43,
+     "execution_count": 45,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -1279,7 +1328,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 44,
+   "execution_count": 46,
    "metadata": {},
    "outputs": [
     {
@@ -1292,7 +1341,7 @@
        " ('Troy', 'Fumagalli', 88)]"
       ]
      },
-     "execution_count": 44,
+     "execution_count": 46,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -1310,7 +1359,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 45,
+   "execution_count": 47,
    "metadata": {},
    "outputs": [
     {
@@ -1323,7 +1372,7 @@
        " ('Jonathan', 'Taylor', 22)]"
       ]
      },
-     "execution_count": 45,
+     "execution_count": 47,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -1349,7 +1398,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.9.7"
+   "version": "3.11.4"
   }
  },
  "nbformat": 4,
diff --git a/f23/Gurmail_Lecture_Notes/23_Function_References/lec_23_function_references_template.ipynb b/f23/Gurmail_Lecture_Notes/23_Function_References/lec_23_function_references_template_Gurmail_lec1.ipynb
similarity index 94%
rename from f23/Gurmail_Lecture_Notes/23_Function_References/lec_23_function_references_template.ipynb
rename to f23/Gurmail_Lecture_Notes/23_Function_References/lec_23_function_references_template_Gurmail_lec1.ipynb
index d39ef000174f67147b7ae86de32664411419575e..431a6ee0d7701903e1d0908cc7192a92154a518e 100644
--- a/f23/Gurmail_Lecture_Notes/23_Function_References/lec_23_function_references_template.ipynb
+++ b/f23/Gurmail_Lecture_Notes/23_Function_References/lec_23_function_references_template_Gurmail_lec1.ipynb
@@ -1,5 +1,21 @@
 {
  "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# Announcements - Monday, October 30\n",
+    "\n",
+    "* Download ALL files for today's lecture\n",
+    "* <b>If you have any problem with P1-P4 grades, please send me (Gurmail.Singh@wisc.edu) an email by November 03.</b>\n",
+    "* If you have questions, it is almost always faster to \n",
+    "  * Post on Piazza\n",
+    "  * Go to [office hours](https://sites.google.com/wisc.edu/cs220-oh-f23/home?pli=1) \n",
+    "### Conflict Form\n",
+    "  * [Exam 2 - November 8, 5:45 pm](https://cs220.cs.wisc.edu/f23/surveys.html)\n",
+    "  * [Final - December 19, 7:45 am](https://cs220.cs.wisc.edu/f23/surveys.html)"
+   ]
+  },
   {
    "cell_type": "markdown",
    "metadata": {},
@@ -14,6 +30,28 @@
     "### Recursion review"
    ]
   },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def fact(n):\n",
+    "    if n == 1:\n",
+    "        return 1\n",
+    "    p = fact(n-1)                                   \n",
+    "    return n * p"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "fact(3)"
+   ]
+  },
   {
    "cell_type": "code",
    "execution_count": null,
@@ -899,7 +937,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.9.7"
+   "version": "3.11.4"
   }
  },
  "nbformat": 4,
diff --git a/f23/Gurmail_Lecture_Notes/23_Function_References/lec_23_function_references_template_Gurmail_lec2.ipynb b/f23/Gurmail_Lecture_Notes/23_Function_References/lec_23_function_references_template_Gurmail_lec2.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..431a6ee0d7701903e1d0908cc7192a92154a518e
--- /dev/null
+++ b/f23/Gurmail_Lecture_Notes/23_Function_References/lec_23_function_references_template_Gurmail_lec2.ipynb
@@ -0,0 +1,945 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# Announcements - Monday, October 30\n",
+    "\n",
+    "* Download ALL files for today's lecture\n",
+    "* <b>If you have any problem with P1-P4 grades, please send me (Gurmail.Singh@wisc.edu) an email by November 03.</b>\n",
+    "* If you have questions, it is almost always faster to \n",
+    "  * Post on Piazza\n",
+    "  * Go to [office hours](https://sites.google.com/wisc.edu/cs220-oh-f23/home?pli=1) \n",
+    "### Conflict Form\n",
+    "  * [Exam 2 - November 8, 5:45 pm](https://cs220.cs.wisc.edu/f23/surveys.html)\n",
+    "  * [Final - December 19, 7:45 am](https://cs220.cs.wisc.edu/f23/surveys.html)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# Function references"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Recursion review"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def fact(n):\n",
+    "    if n == 1:\n",
+    "        return 1\n",
+    "    p = fact(n-1)                                   \n",
+    "    return n * p"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "fact(3)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Nested data structures are defined recursively.\n",
+    "\n",
+    "# A Python list can contain lists\n",
+    "# A Python dictionary can contain dictionaries\n",
+    "# A JSON dictionary can contain a JSON dictionary"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Trace Recursion by hand\n",
+    "# Run this on your own in Python Tutor\n",
+    "\n",
+    "def mystery(a, b): \n",
+    "    # precondition: assume a > 0 and b > 0\n",
+    "    if b == 1: \n",
+    "        return a\n",
+    "    return a * mystery(a, b - 1)\n",
+    "\n",
+    "# make a function call here\n",
+    "mystery(3, 2)\n",
+    "\n",
+    "# TODO: what does the mystery function compute?\n",
+    "\n",
+    "# Question: What would be the result of the below function call?\n",
+    "# mystery(-3, -1) \n",
+    "# Answer: "
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Learning Objectives:\n",
+    "\n",
+    "- Define a function reference and trace code that uses function references.\n",
+    "- Explain the default use of `sorted()` on lists of tuples, and dictionaries.\n",
+    "- Sort a list of tuples, a list of dictionaries, or a dictionary using a function as a key.\n",
+    "- Use a lambda expression when sorting."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Functions are objects\n",
+    "\n",
+    "- Every data in Python is an object instance, including a function definition\n",
+    "- Implications:\n",
+    "    - variables can reference functions\n",
+    "    - lists/dicts can reference functions\n",
+    "    - we can pass function references to other functions\n",
+    "    - we can pass lists of function references to other functions"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Example 1: slide deck example introducing function object references\n",
+    "#### Use PyTutor to step through this example"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "l1 = [1, 2, 3]    # Explanation: l1 should reference a new list object\n",
+    "l2 = l1           # Explanation: l2 should reference whatever l1 references\n",
+    "\n",
+    "def f(l):         # Explanation: f should reference a new function object\n",
+    "    return l[-1]\n",
+    "\n",
+    "g = f             # Explanation: g should reference whatever f references\n",
+    "\n",
+    "num = f(l2)       # Explanation: l should reference whatever l2 references\n",
+    "                  # Explanation: num should reference whatever f returns\n",
+    "\n",
+    "print(num)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Function references\n",
+    "\n",
+    "- Since function definitions are objects in Python, function reference is a variable that refers to a function object.\n",
+    "- In essence, it gives a function another name"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Both these calls would have run the same code, returning the same result\n",
+    "num = f(l1)\n",
+    "num = g(l2) "
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Example 2: function references can be passed as arguments to another function, wow!\n",
+    "#### Use PyTutor to step through this example"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def say_hi():\n",
+    "    print(\"Hello there!\")\n",
+    "\n",
+    "def say_bye():\n",
+    "    print(\"Wash your hands and stay well, bye!\")\n",
+    "    \n",
+    "f = say_hi\n",
+    "f()\n",
+    "f()\n",
+    "f = say_bye\n",
+    "f()\n",
+    "f()\n",
+    "f()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "for i in range(2):\n",
+    "    say_hi()\n",
+    "\n",
+    "for i in range(3):\n",
+    "    say_bye()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def call_n_times(f, n):\n",
+    "    for i in range(n):\n",
+    "        f()\n",
+    "\n",
+    "call_n_times(say_hi, 2)\n",
+    "call_n_times(say_bye, 3)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# call_n_times(say_bye(), 3) # uncomment to see TypeError\n",
+    "\n",
+    "# Question: Why does this give TypeError?\n",
+    "# Answer: when you specify say_bye(), you are invoking the function, which returns None\n",
+    "#         (default return value when return statement is not defined)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Example 3: Apply various transformations to all items on a list"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "L = [\"1\", \"23\", \"456\"]"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "#### Write apply_to_each function"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# a. Input: list object reference, function object\n",
+    "# b. Output: new list reference to transformed object\n",
+    "# c. Pseudocode:\n",
+    "#        1. Initiliaze new empty list for output - we don't want to modify \n",
+    "#           the input list!      \n",
+    "#        2. Process each item in input list\n",
+    "#        3. Apply the function passed as arugment to 2nd parameter\n",
+    "#        4. And the transformed item into output list\n",
+    "#        5. return output list\n",
+    "\n",
+    "def apply_to_each(original_L, f):\n",
+    "    \"\"\"\n",
+    "    returns a new list with transformed items, by applying f function\n",
+    "    to each item in the original list\n",
+    "    \"\"\"\n",
+    "    pass"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Apply `int` function to list L using apply_to_each function"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "#### Write strip_dollar function"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# a. Input: string value\n",
+    "# b. Output: transformed string value\n",
+    "# c. Pseudocode: \n",
+    "#       1. Check whether input string begins with $ - \n",
+    "#          what string method do you need here?\n",
+    "#        2. If so remove it\n",
+    "\n",
+    "def strip_dollar(s):\n",
+    "    \"\"\"\n",
+    "    Removes the beginning $ sign from string s\n",
+    "    \"\"\"\n",
+    "    pass"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Apply strip_dollar function and then apply int function"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "L = [\"$1\", \"23\", \"$456\"]\n",
+    "vals = apply_to_each(L, strip_dollar)\n",
+    "print(vals)\n",
+    "vals = apply_to_each(vals, int)\n",
+    "print(vals)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Apply upper method call to the below list L by using apply_to_each function"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "L = [\"aaa\", \"bbb\", \"ccc\"]\n",
+    "vals = apply_to_each(L, ???)\n",
+    "print(vals)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Custom sorting nested data structures\n",
+    "\n",
+    "Examples:\n",
+    "- list of tuples\n",
+    "- list of dictionaries"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Example 4: Custom sort a list of tuples"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "badgers_in_nfl = [ # tuple storing (first name, last name, age)\n",
+    "                   (\"Jonathan\", \"Taylor\", 22 ), \n",
+    "                   (\"Russel\", \"Wilson\", 32), \n",
+    "                   (\"Troy\", \"Fumagalli\", 88),\n",
+    "                   (\"Melvin\", \"Gordon\", 27), \n",
+    "                   (\"JJ\", \"Watt\", 31),\n",
+    "                 ]\n",
+    "\n",
+    "sorted(badgers_in_nfl) # or sort() method by default uses first element to sort"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "#### What what if we want to sort by the last name or by the length of the name?\n",
+    "\n",
+    "- `sorted` function and `sort` method takes a function reference as keyword argument for the parameter `key`\n",
+    "- We can define functions that take one of the inner data structure as argument and return the field based on which we want to perform the sorting.\n",
+    "    - We then pass a reference to such a function as argument to the parameter `key`.\n",
+    "    \n",
+    "#### Define functions that will enable extraction of item at each tuple index position. These functions only deal with a single tuple processing"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def extract_fname(???):  # function must have exactly one parameter\n",
+    "    return ???\n",
+    "\n",
+    "def extract_lname(player_tuple):\n",
+    "    return ???\n",
+    "\n",
+    "def extract_age(player_tuple):\n",
+    "    return ???"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Test extract_fname function on the tuple ('JJ', 'Watt', 31)\n",
+    "extract_fname(('JJ', 'Watt', 31))"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "#### Sort players by their last name"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "sorted(badgers_in_nfl, ???) "
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "#### Sort players by their age"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "sorted(badgers_in_nfl, ???) "
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "#### Sort players by descending order of age"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "sorted(badgers_in_nfl, ???, ???) "
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "#### Sort players by length of first name + length of last name"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def compute_name_length(player_tuple):\n",
+    "    return ???\n",
+    "\n",
+    "sorted(badgers_in_nfl, ???) "
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Example 5: Custom sort a list of dictionaries"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "hurricanes = [\n",
+    "    {\"name\": \"A\", \"year\": 2000, \"speed\": 150},\n",
+    "    {\"name\": \"B\", \"year\": 1980, \"speed\": 100},\n",
+    "    {\"name\": \"C\", \"year\": 1990, \"speed\": 250},\n",
+    "]"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "#### Extract hurricane at index 0"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "hurricanes[0]"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "#### Extract hurricane at index 1"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "hurricanes[1]"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "#### Can you compare hurricane at index 0 and hurricane at index 1 using \"<\" operator?"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# hurricanes[0] < hurricanes[1] #uncomment to see TypeError"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "#### What about calling sorted method by passing hurricanes as argument?"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# sorted(hurricanes) # Doesn't work because there isn't a defined \"first\" key in a dict.\n",
+    "# Unlike tuple, where the first item can be considered \"first\" by ordering."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Sort hurricanes based on the year"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# a. Input: single hurricane's dict\n",
+    "# b. Output: return \"year\" value from the dict\n",
+    "\n",
+    "def get_year(???):\n",
+    "    ???\n",
+    "\n",
+    "sorted(hurricanes, ???)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Sort hurricanes in descending order of their year"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "sorted(hurricanes, key = get_year, reverse = True) \n",
+    "# alternatively get_year function could return negative of year \n",
+    "# --- that produces the same result as passing True as argument to reverse parameter"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Sort hurricanes in ascending order of their speed"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "hurricanes = [\n",
+    "    {\"name\": \"A\", \"year\": 2000, \"speed\": 150},\n",
+    "    {\"name\": \"B\", \"year\": 1980, \"speed\": 100},\n",
+    "    {\"name\": \"C\", \"year\": 1990}, # notice the missing speed key\n",
+    "]\n",
+    "\n",
+    "def get_speed(hurricane):\n",
+    "    return ???\n",
+    "\n",
+    "sorted(hurricanes, key = get_speed)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Example 6: How can you pass string method to sorted function?"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "sorted([\"A\", \"b\", \"C\", \"d\"])"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "sorted([\"A\", \"b\", \"C\", \"d\"], key = ???)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Sorting dictionary by keys / values"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Example 7: sorting dictionaries"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "players = {\n",
+    "    \"bob\": 20, \n",
+    "    \"alice\": 8, \n",
+    "    \"alex\": 9, \n",
+    "    \"cindy\": 15} # Key: player_name; Value: score\n",
+    "players"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "#### This only returns a list of sorted keys. What if we want to create a new sorted dictionary object directly using sorted function?"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "sorted(players) "
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Let's learn about items method on a dictionary\n",
+    "- returns a list of tuples\n",
+    "- each tuple item contains two items: key and value"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "#### Write an extract function to extract dict value (that is player score), using items method return value"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def extract_score(player_tuple):\n",
+    "    return player_tuple[1]"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Sort players dict by key"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "How can you convert sorted list of tuples back into a `dict`?"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Using `lambda`\n",
+    "- `lambda` functions are a way to abstract a function reference\n",
+    "- lambdas are simple functions with:\n",
+    "    - multiple possible parameters\n",
+    "    - single expression line as the function body\n",
+    "- lambdas are useful abstractions for:\n",
+    "    - mathematical functions\n",
+    "    - lookup operations\n",
+    "- lambdas are often associated with a collection of values within a list\n",
+    "- Syntax: \n",
+    "```python \n",
+    "lambda parameters: expression\n",
+    "```"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Now let's write the same solution using lambda."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "dict(sorted(players.items(), key = ???))"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### What about sorting dictionary by values using lambda?"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "dict(sorted(players.items(), key = ???))"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Now let's sort players dict using length of player name."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "dict(sorted(players.items(), key = ???))"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Self-practice: Use lambdas to solve the NFL sorting questions"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "print(badgers_in_nfl)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "#### Sort players using their first name"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "#### Sort players using their last name"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "#### Sort players using their age"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "#### Sort players using the length of first name and last name"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3 (ipykernel)",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.11.4"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}