{ "cells": [ { "cell_type": "markdown", "id": "b374ef79", "metadata": {}, "source": [ "[Home](Home.ipynb)\n", "\n", "# Lambda Expressions\n", "\n", "\n", "### Bigger Picture\n", "\n", "The Lambda Calculus arose under a bevy of thinkers, at the Institute for Advanced Study at Princeton and elsewhere, to formalize the algebra of composing and defining callables. Recursion is key.\n", "\n", "In the context of our subculture, Lambda Calculus may increase its scope to define a track parallel to Delta Calculus through high school. What used to be the college prep and vocational tracks (shop) has morphed into $\\Delta$ versus $\\Lambda$ calculus, with the latter being \"computer science\" and/or \"discrete math\" in disguise." ] }, { "cell_type": "markdown", "id": "08518ef9", "metadata": {}, "source": [ "### Python in Particular \n", "\"Mary had a little lambda\" we Pythonistas sometimes say, reminding us of the nursery rhyme, but also the Python's lambdas are little. \n", "\n", "\"If you need more than a one liner, you need a named object\" is the implicit advice. In other words, the so-called anonymous function is for expressing simple, primitive operations." ] }, { "cell_type": "markdown", "id": "d8a7810e", "metadata": {}, "source": [ "The lambda expression below gets passed as a first argument to map. map expects a callable and an iterable as arguments, and outputs a map type with \"just in time\" characteristics. Converting a map to a list causes every element to evaluate and we get a final result." ] }, { "cell_type": "code", "execution_count": 1, "id": "430e002f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 0, 1, 1, 2, 2, 3, 3, 4, 4]" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(map(lambda x: x//2, range(10)))" ] }, { "cell_type": "markdown", "id": "5c138b98", "metadata": {}, "source": [ "Map expects a callable that eats a single positional object. You may nevertheless break those objects apart in the body of the callable, including within a lambda expression. \n", "\n", "Fraction expects two arguments, numerator and denominator. The star in front of each tuple *t* e.g. (1, 2) then (1, 3), breaks each tuple into two separate positional arguments." ] }, { "cell_type": "code", "execution_count": 4, "id": "40abe0c8", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[Fraction(1, 2), Fraction(1, 3), Fraction(3, 7), Fraction(5, 12)]" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from fractions import Fraction\n", "list(map(lambda t: Fraction(*t), ((1,2),(1,3),(3,7),(5,12))))" ] }, { "cell_type": "markdown", "id": "bd92454a", "metadata": {}, "source": [ "Python does include a version of map, called starmap, that \"explodes\" each object as it comes in, into separate positional arguments. \n", "\n", "Imagine passing ```*(1,2)``` instead of just ```(1,2)```. That implies consuming two objects instead of one." ] }, { "cell_type": "code", "execution_count": 16, "id": "193ad183", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Wrong number of args\n", "a=1 b=2\n", "All good\n" ] } ], "source": [ "# a short sketch\n", "\n", "def f(a,b):\n", " \"\"\"\n", " eats two objects\n", " \"\"\"\n", " print(f\"a={a} b={b}\")\n", " return a + b\n", "\n", "try:\n", " f((1,2))\n", "except:\n", " print(\"Wrong number of args\")\n", " \n", "try:\n", " f(*(1,2)) # cracks a 2-tuple in two\n", "except:\n", " print(\"Bad news\")\n", "else:\n", " print(\"All good\")" ] }, { "cell_type": "markdown", "id": "de5ecec3", "metadata": {}, "source": [ "And now for ```starmap``` where the star in question is the exploding asterisk. We're now able to craft an intake that eats two objects (in the examples below) or more." ] }, { "cell_type": "code", "execution_count": 12, "id": "ccc873f5", "metadata": {}, "outputs": [], "source": [ "from itertools import starmap" ] }, { "cell_type": "code", "execution_count": 17, "id": "7953849e", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "a=3 b=4\n", "a=5 b=6\n" ] }, { "data": { "text/plain": [ "[7, 11]" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(starmap(f, ((3, 4),(5,6))))" ] }, { "cell_type": "code", "execution_count": 18, "id": "55cdd22f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[Fraction(1, 2), Fraction(1, 3), Fraction(3, 7), Fraction(5, 12)]" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(starmap(lambda n,d: Fraction(n,d), ((1,2),(1,3),(3,7),(5,12))))" ] }, { "cell_type": "markdown", "id": "4407c3dd", "metadata": {}, "source": [ "You might call a lambda expression an \"eater\". \n", "\n", "Try mentally replacing the word lambda with the word eat, and see the expression after the colon as \"doing the thing\" (some operation, some procedure) with whatever's eaten.\n", "\n", "The purpose of the eater is to digest (perform a transformation) and give back (evaluate to a result)." ] }, { "cell_type": "markdown", "id": "9d7606ab", "metadata": {}, "source": [ "### Truth Testing\n", "\n", "In other Notebooks, we explore some theorems from Number Theory, namely Fermat's Little Theorem and Euler's Totient Theorem.\n", "\n", "Fermat's Little Theorem says:\n", "\n", "$(a^{p} - a) \\mid p$ where $p$ is prime and $a$ is any base. \n", "\n", "In other words, any prime $p$ divides $(a^{p} - a)$ without remainder." ] }, { "cell_type": "code", "execution_count": 20, "id": "0a57f35c", "metadata": {}, "outputs": [], "source": [ "from primes import eratosthenes" ] }, { "cell_type": "code", "execution_count": 22, "id": "70afe633", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Eliminating multiples of: 2\n", "Eliminating multiples of: 3\n", "Eliminating multiples of: 5\n", "Eliminating multiples of: 7\n" ] } ], "source": [ "the_primes = eratosthenes(100)" ] }, { "cell_type": "code", "execution_count": 32, "id": "e795f0eb", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]\n" ] } ], "source": [ "print(\n", " list(filter(\n", " lambda p: divmod(4**p - 4, p)[1] == 0, the_primes))\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "490a7d15", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "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.7.9" } }, "nbformat": 4, "nbformat_minor": 5 }