Created
February 19, 2023 14:11
-
-
Save eriknw/adc62045e57435736d81646a3c6f499f to your computer and use it in GitHub Desktop.
Functional Programming Lightning Talk (blocksum example)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "cells": [ | |
| { | |
| "cell_type": "markdown", | |
| "id": "76d38692-684f-4079-a3a9-95c08d5458ae", | |
| "metadata": {}, | |
| "source": [ | |
| "# Functional Programming in Python by Example\n", | |
| "## Me: Erik Welch (https://github.com/eriknw)\n", | |
| "### maintainer of `toolz` and `cytoolz` functional programming packages (~10 years)\n", | |
| "- `toolz` is the #222 most popular package on PyPI in the last month\n", | |
| "- About 16_500_000 downloads from PyPI in the last month" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 1, | |
| "id": "f07456d0-262b-4592-89d9-4192c36141ac", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "import random\n", | |
| "import numpy as np\n", | |
| "from pprint import pprint\n", | |
| "\n", | |
| "def show(list_of_lists):\n", | |
| " pprint(list(list(row) for row in list_of_lists), width=20)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 2, | |
| "id": "f191a52e-9c31-45e2-8f1b-607cb7fbb85f", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "data = [\n", | |
| " [2, 4, 3],\n", | |
| " [1, 2, 1],\n", | |
| " [9, 2, 3],\n", | |
| "]" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "ea5969b2-3a49-4b6c-8ab3-db94e876fe17", | |
| "metadata": {}, | |
| "source": [ | |
| "**input**: list of list of numbers\n", | |
| "\n", | |
| "**output**: list of list of numbers (same shape as input) \n", | |
| "- `output[i][j]` = sum of all `inputs[ii][jj]` where `ii <= i` and `jj <= j`" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 3, | |
| "id": "3eb0d0d8-303d-400f-92a9-c337a47956a2", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "def simple(data):\n", | |
| " rv = [[0] * len(row) for row in data]\n", | |
| " for i, row in enumerate(data):\n", | |
| " for j, val in enumerate(row):\n", | |
| " for ii in range(i + 1):\n", | |
| " for jj in range(j + 1):\n", | |
| " rv[i][j] = rv[i][j] + data[ii][jj]\n", | |
| " return rv" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 4, | |
| "id": "9c43e8a2-fdc4-4f94-857b-c9df61c48238", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "[[2, 4, 3],\n", | |
| " [1, 2, 1],\n", | |
| " [9, 2, 3]]\n", | |
| "->\n", | |
| "[[2, 6, 9],\n", | |
| " [3, 9, 13],\n", | |
| " [12, 20, 27]]\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "show(data)\n", | |
| "print('->')\n", | |
| "show(simple(data))" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 5, | |
| "id": "edc8f664-387f-4289-b93b-d067c118f31e", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "[[1, 1, 1],\n", | |
| " [1, 1, 1],\n", | |
| " [1, 1, 1]]\n", | |
| "->\n", | |
| "[[1, 2, 3],\n", | |
| " [2, 4, 6],\n", | |
| " [3, 6, 9]]\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "ones = [[1, 1, 1]] * 3\n", | |
| "show(ones)\n", | |
| "print('->')\n", | |
| "show(simple(ones))" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 6, | |
| "id": "adc9c27d-fa2a-40ce-8e91-247b48c072c3", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "from itertools import accumulate as accum\n", | |
| "from operator import add" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 7, | |
| "id": "d24b79dd-122e-4fde-bde1-a1b6cabb18b0", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "[[1, 1, 1],\n", | |
| " [1, 1, 1],\n", | |
| " [1, 1, 1]]\n", | |
| "-> cumsums ->\n", | |
| "[[1, 2, 3],\n", | |
| " [1, 2, 3],\n", | |
| " [1, 2, 3]]\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "# cumsum for each row\n", | |
| "show(ones)\n", | |
| "print('-> cumsums ->')\n", | |
| "show([\n", | |
| " accum(row, add) for row in ones\n", | |
| "])" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 8, | |
| "id": "ae70fc3c-54e7-4468-9e05-ab0fd3675ae0", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "[[2, 4, 3],\n", | |
| " [1, 2, 1],\n", | |
| " [9, 2, 3]]\n", | |
| "-> transpose ->\n", | |
| "[[2, 1, 9],\n", | |
| " [4, 2, 2],\n", | |
| " [3, 1, 3]]\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "show(data)\n", | |
| "print(\"-> transpose ->\")\n", | |
| "show(zip(*data))" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 9, | |
| "id": "dfa62d6e-e488-43d8-ac8c-4d2dcfaad836", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "[[1, 1, 1],\n", | |
| " [2, 2, 2],\n", | |
| " [3, 3, 3]]\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "show(\n", | |
| " zip(*(accum(row, add) for row in ones))\n", | |
| ")" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 10, | |
| "id": "61b80cc6-ee62-4ba3-bd1b-750527362cf1", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "[[1, 2, 3],\n", | |
| " [2, 4, 6],\n", | |
| " [3, 6, 9]]\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "show([\n", | |
| " accum(col, add)\n", | |
| " for col in zip(*(accum(row, add) for row in ones))\n", | |
| "])" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 11, | |
| "id": "0dc1b1ee-4a51-4a6b-8e41-eaa69ad908b9", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "[[2, 4, 3],\n", | |
| " [1, 2, 1],\n", | |
| " [9, 2, 3]]\n", | |
| "-> cumsums -> transpose -> cumsums ->\n", | |
| "[[2, 3, 12],\n", | |
| " [6, 9, 20],\n", | |
| " [9, 13, 27]]\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "show(data)\n", | |
| "print(\"-> cumsums -> transpose -> cumsums ->\")\n", | |
| "show([\n", | |
| " accum(col, add)\n", | |
| " for col in zip(*(accum(row, add) for row in data))\n", | |
| "])" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 12, | |
| "id": "574a4139-7cd6-487b-9583-0742f84bb0c1", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "[[2, 4, 3],\n", | |
| " [1, 2, 1],\n", | |
| " [9, 2, 3]]\n", | |
| "-> cumsums -> transpose -> cumsums -> transpose\n", | |
| "[[2, 6, 9],\n", | |
| " [3, 9, 13],\n", | |
| " [12, 20, 27]]\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "show(data)\n", | |
| "print(\"-> cumsums -> transpose -> cumsums -> transpose\")\n", | |
| "show(\n", | |
| " zip(*(\n", | |
| " accum(col, add) for col in zip(*(\n", | |
| " accum(row, add) for row in data\n", | |
| " ))\n", | |
| " ))\n", | |
| ")" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 13, | |
| "id": "6faf0795-f2ca-4288-b129-6cb23c8d5327", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "def cumsum(seq):\n", | |
| " prev = 0\n", | |
| " return [prev := x + prev for x in seq]" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 14, | |
| "id": "5d3d0688-d0c6-4db8-a1c5-4eb78e557baa", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "[[2, 4, 3],\n", | |
| " [1, 2, 1],\n", | |
| " [9, 2, 3]]\n", | |
| "-> cumsums -> transpose -> cumsums -> transpose\n", | |
| "[[2, 6, 9],\n", | |
| " [3, 9, 13],\n", | |
| " [12, 20, 27]]\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "show(data)\n", | |
| "print(\"-> cumsums -> transpose -> cumsums -> transpose\")\n", | |
| "show(\n", | |
| " zip(*(\n", | |
| " cumsum(col) for col in zip(*(\n", | |
| " cumsum(row) for row in data\n", | |
| " ))\n", | |
| " ))\n", | |
| ")" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 15, | |
| "id": "1a912828-2772-41d5-8b9e-3db8f492f001", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "def transpose(seq):\n", | |
| " return zip(*seq)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 16, | |
| "id": "89332d21-f38f-4739-8c76-d4e8bbb6f331", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "[[2, 4, 3],\n", | |
| " [1, 2, 1],\n", | |
| " [9, 2, 3]]\n", | |
| "-> cumsums -> transpose -> cumsums -> transpose\n", | |
| "[[2, 6, 9],\n", | |
| " [3, 9, 13],\n", | |
| " [12, 20, 27]]\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "show(data)\n", | |
| "print(\"-> cumsums -> transpose -> cumsums -> transpose\")\n", | |
| "show(\n", | |
| " transpose(\n", | |
| " cumsum(col) for col in transpose(\n", | |
| " cumsum(row) for row in data\n", | |
| " )\n", | |
| " )\n", | |
| ")" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 17, | |
| "id": "c75ac688-0d9e-4624-8c91-66165bac3323", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "[[2, 4, 3],\n", | |
| " [1, 2, 1],\n", | |
| " [9, 2, 3]]\n", | |
| "-> cumsums -> transpose -> cumsums -> transpose\n", | |
| "[[2, 6, 9],\n", | |
| " [3, 9, 13],\n", | |
| " [12, 20, 27]]\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "show(data)\n", | |
| "print(\"-> cumsums -> transpose -> cumsums -> transpose\")\n", | |
| "show(\n", | |
| " transpose(cumsum(col) for col in transpose(cumsum(row) for row in data))\n", | |
| ")" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 18, | |
| "id": "70c68923-355c-4c80-aedb-19f1a269bf58", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "[[2, 4, 3],\n", | |
| " [1, 2, 1],\n", | |
| " [9, 2, 3]]\n", | |
| "-> cumsums -> transpose -> cumsums -> transpose\n", | |
| "[[2, 6, 9],\n", | |
| " [3, 9, 13],\n", | |
| " [12, 20, 27]]\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "show(data)\n", | |
| "print(\"-> cumsums -> transpose -> cumsums -> transpose\")\n", | |
| "show(\n", | |
| " transpose(map(cumsum, transpose(map(cumsum, data))))\n", | |
| ")" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 19, | |
| "id": "81428447-dc57-4e0f-9500-7f595dc798b0", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "def cumsums(data):\n", | |
| " return map(cumsum, data)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 20, | |
| "id": "1ff13e4a-f013-4380-95eb-fb170e16990b", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "[[2, 4, 3],\n", | |
| " [1, 2, 1],\n", | |
| " [9, 2, 3]]\n", | |
| "-> cumsums -> transpose -> cumsums -> transpose\n", | |
| "[[2, 6, 9],\n", | |
| " [3, 9, 13],\n", | |
| " [12, 20, 27]]\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "show(data)\n", | |
| "print(\"-> cumsums -> transpose -> cumsums -> transpose\")\n", | |
| "show(\n", | |
| " transpose(cumsums(transpose(cumsums(data))))\n", | |
| ")" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 21, | |
| "id": "108f36a4-94c2-4e8c-896d-0b8ce856032f", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "def pipe(data, *funcs):\n", | |
| " for func in funcs:\n", | |
| " data = func(data)\n", | |
| " return data" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 22, | |
| "id": "25ec6d66-5708-499d-9c6c-fcb3d52e2533", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "[[2, 4, 3],\n", | |
| " [1, 2, 1],\n", | |
| " [9, 2, 3]]\n", | |
| "-> cumsums -> transpose -> cumsums -> transpose\n", | |
| "[[2, 6, 9],\n", | |
| " [3, 9, 13],\n", | |
| " [12, 20, 27]]\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "show(data)\n", | |
| "print(\"-> cumsums -> transpose -> cumsums -> transpose\")\n", | |
| "show(\n", | |
| " pipe(data, cumsums, transpose, cumsums, transpose)\n", | |
| ")" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 23, | |
| "id": "90d101b4-5391-4daa-b092-8e885f64abab", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "def cmap(func):\n", | |
| " def curried_map(seq):\n", | |
| " return map(func, seq)\n", | |
| " return curried_map" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 24, | |
| "id": "c45170e3-48f8-43e5-80c3-e61958a2350a", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "[[2, 4, 3],\n", | |
| " [1, 2, 1],\n", | |
| " [9, 2, 3]]\n", | |
| "-> cumsums -> transpose -> cumsums -> transpose\n", | |
| "[[2, 6, 9],\n", | |
| " [3, 9, 13],\n", | |
| " [12, 20, 27]]\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "show(data)\n", | |
| "print(\"-> cumsums -> transpose -> cumsums -> transpose\")\n", | |
| "show(\n", | |
| " pipe(data, cmap(cumsum), transpose, cmap(cumsum), transpose)\n", | |
| ")" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 25, | |
| "id": "032412ea-f6e4-4186-bf00-534973d74ea4", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "\u001b[0;31mInit signature:\u001b[0m \u001b[0maccum\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0miterable\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0minitial\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", | |
| "\u001b[0;31mDocstring:\u001b[0m Return series of accumulated sums (or other binary function results).\n", | |
| "\u001b[0;31mType:\u001b[0m type\n", | |
| "\u001b[0;31mSubclasses:\u001b[0m " | |
| ] | |
| }, | |
| "metadata": {}, | |
| "output_type": "display_data" | |
| } | |
| ], | |
| "source": [ | |
| "accum?" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 26, | |
| "id": "545cc4e6-d3c9-4f38-af78-2a3816e1ed0b", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "[[2, 4, 3],\n", | |
| " [1, 2, 1],\n", | |
| " [9, 2, 3]]\n", | |
| "-> cumsums -> transpose -> cumsums -> transpose\n", | |
| "[[2, 6, 9],\n", | |
| " [3, 9, 13],\n", | |
| " [12, 20, 27]]\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "show(data)\n", | |
| "print(\"-> cumsums -> transpose -> cumsums -> transpose\")\n", | |
| "show(\n", | |
| " pipe(data, cmap(accum), transpose, cmap(accum), transpose)\n", | |
| ")" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 27, | |
| "id": "37eca2f4-1390-45d9-a6b2-f4c87271286e", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "def blocksum(data):\n", | |
| " return pipe(data, cmap(accum), transpose, cmap(accum), transpose, list)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 28, | |
| "id": "5db396bc-1915-43bb-b361-bd0d8bcd983c", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "def blocksum_alt1(data):\n", | |
| " return pipe(data, cmap(cumsum), transpose, cmap(cumsum), transpose, list)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 29, | |
| "id": "14c08873-d036-4a67-8062-d13bb29f83cd", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "def blocksum_alt2(data):\n", | |
| " return list(zip(*(\n", | |
| " accum(col) for col in zip(*(\n", | |
| " accum(row) for row in data\n", | |
| " ))\n", | |
| " )))" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 30, | |
| "id": "c5bb4f2f-5602-4400-9d29-cb3134deb350", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "def blocksum_numpy(data):\n", | |
| " # Convert input to NumPy array and convert result to Python list\n", | |
| " return np.array(data).cumsum(axis=0).cumsum(axis=1).tolist()" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 31, | |
| "id": "ba5ceeff-56a4-4ec0-9619-3ff3d3de5014", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "def blocksum_proc(data):\n", | |
| " # Optimized version of procedural style\n", | |
| " rv = []\n", | |
| " prevrow = [0] * len(data)\n", | |
| " for row in data:\n", | |
| " cur = []\n", | |
| " left = 0\n", | |
| " for val, above in zip(row, prevrow):\n", | |
| " left += val + above\n", | |
| " cur.append(left)\n", | |
| " prevrow = row\n", | |
| " rv.append(cur)\n", | |
| " return rv" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "4dbd6d4e-5a44-47a5-b7d6-5dceab4d31b8", | |
| "metadata": {}, | |
| "source": [ | |
| "## Benchmarks" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 32, | |
| "id": "e5f2be73-72ee-4acd-bb74-6a39d5ed23f4", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "bigshape = (200, 200)\n", | |
| "bigdata = [[random.randint(1, 9) for _ in range(bigshape[1])] for _ in range(bigshape[0])]" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 33, | |
| "id": "9e71cf47-b7d8-4f5f-8a07-c17166b64290", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "1.77 ms ± 121 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "%timeit blocksum(bigdata)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 34, | |
| "id": "b6230c4a-7db4-4d97-bad5-4b0067ce53f2", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "2.84 ms ± 76.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "%timeit blocksum_alt1(bigdata)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 35, | |
| "id": "591a7318-cbd0-49c9-800c-11a98ab8a1de", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "1.78 ms ± 46.5 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "%timeit blocksum_alt2(bigdata)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 36, | |
| "id": "0bea8d9d-7617-4ecc-b24a-eec708857c3b", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "2.11 ms ± 66.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "%timeit blocksum_numpy(bigdata)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 37, | |
| "id": "c86fb452-d08a-4a66-96f1-5fecadc7b7f6", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "2.47 ms ± 173 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "%timeit blocksum_proc(bigdata)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 38, | |
| "id": "7682e133-471b-452d-9f59-3ca714d5f39d", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "CPU times: user 25.9 s, sys: 0 ns, total: 25.9 s\n", | |
| "Wall time: 25.9 s\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "%time _ = simple(bigdata) # more than 15_000 times slower!" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "id": "ffa80da2-1252-4243-bdd1-0af54a4c289b", | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 39, | |
| "id": "5c890cb3-d5e1-4b25-a28c-80fa1a33b22e", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "hugeshape = (1000, 1000)\n", | |
| "hugedata = [[random.randint(1, 9) for _ in range(hugeshape[1])] for _ in range(hugeshape[0])]" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 40, | |
| "id": "f3bbc1a3-498d-4d47-bbec-020f0554b740", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "71.6 ms ± 1.53 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "%timeit blocksum(hugedata)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 41, | |
| "id": "8675cd35-4232-4343-b45c-6d98de0b9f39", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "61.4 ms ± 628 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "%timeit blocksum_numpy(hugedata)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 42, | |
| "id": "e07dbe48-c1d0-4716-8a3c-28c1a1e070cf", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "68.8 ms ± 2.93 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "%timeit blocksum_proc(hugedata)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "36027687-432a-4b3f-9173-cba5165a0625", | |
| "metadata": {}, | |
| "source": [ | |
| "## `toolz` gives you the building blocks for writing clear functional-syle programming in Python\n", | |
| "### and `cytoolz` is a faster version of `toolz` written in Cython\n", | |
| "*Pro tip: use `tlz` to use the fastest version of `toolz` or `cytoolz` available*" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 43, | |
| "id": "b4e532e2-7df1-432c-9255-a6e96d26908e", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "from tlz.curried import map, pipe, accumulate" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 44, | |
| "id": "80afffd4-5b33-4e5a-bfaf-ebe94f034071", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "[[2, 6, 9],\n", | |
| " [3, 9, 13],\n", | |
| " [12, 20, 27]]\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "pipe(\n", | |
| " data,\n", | |
| " map(accumulate(add)), # cumsum row-wise\n", | |
| " transpose,\n", | |
| " map(accumulate(add)), # cumsum column-wise\n", | |
| " transpose,\n", | |
| " show,\n", | |
| ")" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "91215569-d0ca-4161-b9b2-d0c34c3391cb", | |
| "metadata": {}, | |
| "source": [ | |
| "# Thank you!\n", | |
| "## Me: Erik Welch (https://github.com/eriknw)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "0d979add-a5a8-48b0-ac9c-4b0e8ea047e4", | |
| "metadata": {}, | |
| "source": [ | |
| "Bonus content--what is happening here?!" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 45, | |
| "id": "2b55eaa6-4e00-4c11-a693-bb2c59f89a3d", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "@(curry := lambda n, *a: lambda f: lambda *b: f(*c) if len(c := a + b) >= n else curry(n, *c)(f))(3)\n", | |
| "def add3(*args):\n", | |
| " assert len(args) >= 3\n", | |
| " return sum(args)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 46, | |
| "id": "437c4bcb-db9f-49f9-b974-e6fac4467919", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "6" | |
| ] | |
| }, | |
| "execution_count": 46, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "add3(1)(2)(3)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 47, | |
| "id": "75d1cdd2-b739-47ce-ab9b-156e01b4317b", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "6" | |
| ] | |
| }, | |
| "execution_count": 47, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "add3(1, 2)()()(3)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 48, | |
| "id": "f905cd7d-bd17-452e-8856-d7b55bcea986", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "6" | |
| ] | |
| }, | |
| "execution_count": 48, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "add3(1, 2, 3)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 49, | |
| "id": "bb5c192e-ad54-4e3d-8c60-153d53e95818", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "# This is equivalent to the above\n", | |
| "def curry(n, *a):\n", | |
| " def decorator(func):\n", | |
| " def wrapper(*b):\n", | |
| " c = a + b\n", | |
| " if len(c) >= n:\n", | |
| " return func(*c)\n", | |
| " return curry(n, *c)(func)\n", | |
| " return wrapper\n", | |
| " return decorator\n", | |
| "\n", | |
| "\n", | |
| "@curry(3)\n", | |
| "def add3(*args):\n", | |
| " assert len(args) >= 3\n", | |
| " return sum(args)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 50, | |
| "id": "9bf10183-556b-4001-8b30-d6907c8c4c10", | |
| "metadata": { | |
| "tags": [] | |
| }, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/plain": [ | |
| "True" | |
| ] | |
| }, | |
| "execution_count": 50, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "add3(1, 2)(3) == add3(1)(2)(3) == 6" | |
| ] | |
| } | |
| ], | |
| "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.10.9" | |
| } | |
| }, | |
| "nbformat": 4, | |
| "nbformat_minor": 5 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment