Skip to content

Instantly share code, notes, and snippets.

@eriknw
Created February 19, 2023 14:11
Show Gist options
  • Save eriknw/adc62045e57435736d81646a3c6f499f to your computer and use it in GitHub Desktop.
Save eriknw/adc62045e57435736d81646a3c6f499f to your computer and use it in GitHub Desktop.
Functional Programming Lightning Talk (blocksum example)
Display the source blob
Display the rendered blob
Raw
{
"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