summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElizabeth Hunt <elizabeth.hunt@simponic.xyz>2024-02-12 10:33:17 -0700
committerElizabeth Hunt <elizabeth.hunt@simponic.xyz>2024-02-12 10:33:17 -0700
commit512c245466fad78106a046c1ea6233acdcc3e4de (patch)
treeff1599ae375b86a39114b10ffd18e5c9a81a44f5
parentc55d9d2832a46d9dc265fec36936b1313f5af6f6 (diff)
downloadcompiling-the-lambda-calculus-512c245466fad78106a046c1ea6233acdcc3e4de.tar.gz
compiling-the-lambda-calculus-512c245466fad78106a046c1ea6233acdcc3e4de.zip
add generatlized
-rw-r--r--script.md35
-rw-r--r--src/components/function_box.tsx8
-rw-r--r--src/scenes/birthday_letters.tsx10
-rw-r--r--src/scenes/generalized.meta5
-rw-r--r--src/scenes/generalized.tsx212
-rw-r--r--src/scenes/index.ts6
6 files changed, 235 insertions, 41 deletions
diff --git a/script.md b/script.md
index 585d74e..088ed0f 100644
--- a/script.md
+++ b/script.md
@@ -105,36 +105,11 @@ There, now, we can make sure our friends are happy on their birthdays!
But, this is getting annoying; what about Christmas, Thanksgiving, or Easter? Making a new black box to make a list of new cards, going through each person, every single time to construct a list of cards, is getting really tedious.
-What if we generalized this? We create a bunch of black boxes that take a person, and generate them a card, specifically; like a template for a card you could print off and fill in manually.
+[SPACE] What if we generalized this? [SPACE] We create a couple of black boxes that take a person, and generate them a card, specifically; like a template for a card you could print off and fill in manually. Like this, for alan turing.
-```python
-def valentine_letter(person):
- return f"Dear, {person.name}\nYour smile lights up my world. Happy Valentine's Day!")
-
-def birthday_card(person):
- today = new Date()
- daysUntilBirthday = toDays(new Date(person.birthday, today.year) - today)
- newAge = today.year - person.birthday.year
-
- card = f"Happy Birthday {name}\nI can't believe you're already {newAge} years old!"
- cards.append({ "message": card, "deliverInDays": daysUntilBirthday })
-```
-
-Then, we can use a black box that takes a list of people, and applies this template to each person.
-
-```
-def buildCards(people, cardMaker):
- cards = []
- for person in people:
- card = cardMaker(person)
- cards.append(card)
- return cards
-
-people = [{"name": "Joseph", birthday: new Date()}, {"name": "DeeDee", birthday: new Date()}]
-buildCards(people, birthdayCard)
-```
+Then, we can use a new black box that takes a list of people, and applies this template to each person.
-The ability in a language to pass a function around like this - like a variable - is what makes functions "first class". And the `buildCards` function takes a function as input, making it a "higher order function". (TODO: slides)
+The ability in a language to pass a function around like this - like a variable - is what makes functions "first class". And the `buildCards` function takes a function as input, making it a "higher order function".
Functional Reproduction
===
@@ -211,7 +186,7 @@ Immutability
===
We briefly mentioned side effects and alluded them to the unpredictability of a partner. We love our black boxes because they're reliable.
-But, we've actually had an impostor among us (AMOGUS sound??) throughout this presentation. Specifically in ~buildCards~:
+But, we've actually had an impostor among us (AMOGUS sound??) throughout this presentation. Specifically in `buildCards`:
```
def buildCards(people, cardMaker):
@@ -244,7 +219,7 @@ def build_cards(people, card_maker):
return [card] + build_cards(rest_people, card_maker)
```
-Here we're not changing anything at all (except the stack), with the same functionality; this code is "immutable". When we call ~build_cards~ on a list of people, we're 100% certain we're not gonna get something odd short of a bug.
+Here we're not changing anything at all (except the stack), with the same functionality; this code is "immutable". When we call `build_cards` on a list of people, we're 100% certain we're not gonna get something odd short of a bug.
At a high level there are so many benefits to immutability:
+ Concurrency (TODO: go into more detail)
diff --git a/src/components/function_box.tsx b/src/components/function_box.tsx
index b2221b4..e1ed497 100644
--- a/src/components/function_box.tsx
+++ b/src/components/function_box.tsx
@@ -86,7 +86,7 @@ export class FunctionBox extends Node {
alignItems={"center"}
layout
>
- <Rect direction={"column"} alignItems={"end"}>
+ <Rect direction={"column"} alignItems={"end"} gap={10}>
{range(this.arity).map((i) => (
<Rect direction={"row"} alignItems={"center"} gap={10}>
<Rect
@@ -116,8 +116,9 @@ export class FunctionBox extends Node {
fill={theme.crust.hex}
lineWidth={4}
padding={60}
- direction={"row"}
- height={"100%"}
+ direction="row"
+ height="100%"
+ alignItems="center"
>
<Txt fontFamily={theme.font} fill={theme.text.hex} ref={this.boxMoji}>
{this.idlingText}
@@ -273,7 +274,6 @@ export class FunctionBox extends Node {
<CodeBlock
fontFamily={theme.font}
language="typescript"
- fontSize={this.outputFontSize}
code={JSON.stringify(output, null, 2)}
></CodeBlock>,
);
diff --git a/src/scenes/birthday_letters.tsx b/src/scenes/birthday_letters.tsx
index 2a63360..8fe7990 100644
--- a/src/scenes/birthday_letters.tsx
+++ b/src/scenes/birthday_letters.tsx
@@ -13,13 +13,13 @@ import { FunctionBox } from "../components/function_box";
import { theme } from "../theme";
import { PEOPLE, Person, PersonI } from "../components/person";
-const daysUntilNextBirthday = (birthDate: Date): number => {
+export const daysUntilNextDate = (date: Date): number => {
const today = new Date();
const nextBirthday = new Date(
today.getFullYear(),
- birthDate.getMonth(),
- birthDate.getDate(),
+ date.getMonth(),
+ date.getDate(),
);
if (today > nextBirthday) nextBirthday.setFullYear(today.getFullYear() + 1);
@@ -45,7 +45,7 @@ export const birthdayCardsFor = (people: PersonI[]): CardI[] => {
`Happy ${age}${ending} birthday, ${person.name}!\n` +
"I can't believe it's already been a year!";
- const deliverInDays = daysUntilNextBirthday(person.birthday);
+ const deliverInDays = daysUntilNextDate(person.birthday);
cards.push({ deliverInDays, message });
}
@@ -70,7 +70,7 @@ const birthdayCardsFor = (people: PersonI[]): CardI[] => {
\`Happy \${age}\${ageEnding} birthday, \${person.name}!\\n\` +
"I can't believe it's already been a year!";
- const deliverInDays = daysUntilNextBirthday(person.birthday);
+ const deliverInDays = daysUntilNextDate(person.birthday);
cards.push({ deliverInDays, message });
}
diff --git a/src/scenes/generalized.meta b/src/scenes/generalized.meta
new file mode 100644
index 0000000..46b4f46
--- /dev/null
+++ b/src/scenes/generalized.meta
@@ -0,0 +1,5 @@
+{
+ "version": 0,
+ "timeEvents": [],
+ "seed": 3138224359
+} \ No newline at end of file
diff --git a/src/scenes/generalized.tsx b/src/scenes/generalized.tsx
new file mode 100644
index 0000000..67cbb31
--- /dev/null
+++ b/src/scenes/generalized.tsx
@@ -0,0 +1,212 @@
+import { Layout, Txt, makeScene2D } from "@motion-canvas/2d";
+import {
+ Direction,
+ all,
+ beginSlide,
+ createRef,
+ slideTransition,
+} from "@motion-canvas/core";
+
+import { FunctionBox } from "../components/function_box";
+import { PEOPLE, Person, PersonI } from "../components/person";
+import { CardI, daysUntilNextDate } from "./birthday_letters";
+
+const valentineCardFn = (person: PersonI): CardI => {
+ const valentinesDay = new Date("02/14/2024");
+ const message =
+ `Dear, ${person.name}\n.` +
+ "Your smile lights up my world.\n" +
+ "Happy Valentine's Day!";
+ const deliverInDays = daysUntilNextDate(valentinesDay);
+ return { message, deliverInDays };
+};
+
+const birthdayCardFn = (person: PersonI): CardI => {
+ const age = new Date().getFullYear() - person.birthday.getFullYear();
+ const ending =
+ ({ 1: "st", 2: "nd", 3: "rd" } as Record<number, string>)[
+ parseInt(Array.from(age.toString()).at(-1))
+ ] ?? "th";
+ const message =
+ `Happy ${age}${ending} birthday, ${person.name}!\n` +
+ "I can't believe it's already been a year!";
+
+ const deliverInDays = daysUntilNextDate(person.birthday);
+ return { deliverInDays, message };
+};
+
+const valentineCardGenerator = `const valentineCardGenerator = (person: PersonI): CardI => {
+ const valentinesDay = new Date("02/14/2024");
+ const message =
+ \`Dear, \${person.name}\\n.\` +
+ "Your smile lights up my world.\\n" +
+ "Happy Valentine's Day!";
+ const deliverInDays = daysUntilNextDate(valentinesDay);
+ return { message, deliverInDays };
+};`;
+
+const birthdayCardGenerator = `const birthdayCardGenerator = (person: PersonI): CardI => {
+ const age = new Date().getFullYear() - person.birthday.getFullYear();
+ const ageEnding = (
+ { 1: "st", 2: "nd", 3: "rd" } as Record<number, string>
+ )[parseInt(Array.from(age.toString()).at(-1))] ?? "th";
+
+ const message =
+ \`Happy \${age}\${ageEnding} birthday, \${person.name}!\\n\` +
+ "I can't believe it's already been a year!";
+
+ const deliverInDays = daysUntilNextDate(person.birthday);
+ return { deliverInDays, message };
+}`;
+
+const cardBuilder = `const buildCards = (
+ people: PersonI[],
+ cardGenerator: (person: PersonI) => CardI,
+): CardI[] => {
+ const cards: CardI[] = [];
+
+ for (const person of people) {
+ const card = cardGenerator(person);
+ cards.push(card);
+ }
+
+ return cards;
+};
+buildCards;`;
+
+export default makeScene2D(function* (view) {
+ const valentineFunctionBox = createRef<FunctionBox>();
+ const birthdayFunctionBox = createRef<FunctionBox>();
+ const cardBuilderBox = createRef<FunctionBox>();
+ const layout = createRef<Layout>();
+
+ view.add(
+ <Layout direction="row" gap={200} ref={layout} layout>
+ <Layout direction="column" alignItems="center" gap={20}>
+ <FunctionBox
+ ref={valentineFunctionBox}
+ source={valentineCardGenerator}
+ fn={valentineCardFn}
+ idlingText="❤️"
+ workingText="📝⚙"
+ outputFontSize={15}
+ ></FunctionBox>
+ <FunctionBox
+ ref={birthdayFunctionBox}
+ source={birthdayCardGenerator}
+ fn={birthdayCardFn}
+ idlingText="🎂"
+ workingText="📝⚙"
+ outputFontSize={15}
+ ></FunctionBox>
+ </Layout>
+ <Layout direction="column" gap={20}>
+ <FunctionBox
+ ref={cardBuilderBox}
+ source={cardBuilder}
+ idlingText="🏭"
+ workingText="📝⚙"
+ outputFontSize={15}
+ arity={2}
+ ></FunctionBox>
+ </Layout>
+ </Layout>,
+ );
+
+ yield* all(
+ slideTransition(Direction.Left),
+ ...[valentineFunctionBox, birthdayFunctionBox, cardBuilderBox].map((x) =>
+ x().reset(0.1),
+ ),
+ );
+
+ yield* beginSlide("show all functions");
+
+ yield* all(
+ ...[valentineFunctionBox, birthdayFunctionBox].map((x) =>
+ x().showCode(0.5),
+ ),
+ );
+
+ yield* beginSlide("show generator functions");
+
+ const [p1, p2, p3, p4] = PEOPLE;
+ yield* all(
+ ...[valentineFunctionBox, birthdayFunctionBox].map((x) =>
+ x().hideCode(0.5),
+ ),
+ );
+ yield* all(
+ ...[valentineFunctionBox, birthdayFunctionBox].map((x) =>
+ x().setInputs([{ val: p2, node: <Person person={p2} /> }], 0.5),
+ ),
+ );
+
+ yield* beginSlide("show inputs");
+
+ yield* all(
+ ...[valentineFunctionBox, birthdayFunctionBox].map((x) =>
+ x().propogateInput(0.5),
+ ),
+ );
+ yield* all(
+ ...[valentineFunctionBox, birthdayFunctionBox].map((x) =>
+ x().propogateOutput(0.5),
+ ),
+ );
+ yield* beginSlide("make cards");
+
+ yield* all(
+ ...[valentineFunctionBox, birthdayFunctionBox].map((x) => x().reset(0.5)),
+ cardBuilderBox().showCode(0.5),
+ );
+
+ yield* beginSlide("hide cards, show card generator");
+
+ yield* cardBuilderBox().setInputs(
+ [
+ {
+ val: [p1, p2],
+ node: (
+ <Layout direction="row" gap={20}>
+ <Person person={p1} />
+ <Person person={p2} />
+ </Layout>
+ ),
+ },
+ { val: valentineCardFn, node: valentineFunctionBox() },
+ ],
+ 0.5,
+ );
+ yield* beginSlide("input function to function");
+
+ yield* cardBuilderBox().hideCode(0.5);
+ yield* cardBuilderBox().propogateInput(0.5);
+ yield* cardBuilderBox().propogateOutput(0.5);
+
+ yield* beginSlide("build valentines cards");
+
+ yield* all(layout().gap(0, 0.5), cardBuilderBox().reset(0.5));
+ yield* cardBuilderBox().setInputs(
+ [
+ {
+ val: [p2, p3, p4],
+ node: (
+ <Layout direction="row" gap={20}>
+ <Person person={p2} />
+ <Person person={p3} />
+ <Person person={p4} />
+ </Layout>
+ ),
+ },
+ { val: birthdayCardFn, node: birthdayFunctionBox() },
+ ],
+ 0.5,
+ );
+ yield* beginSlide("show birthday cards input");
+
+ yield* cardBuilderBox().propogateInput(0.5);
+ yield* cardBuilderBox().propogateOutput(0.5);
+
+ yield* beginSlide("build cards");
+});
diff --git a/src/scenes/index.ts b/src/scenes/index.ts
index 8b53e09..6f09c88 100644
--- a/src/scenes/index.ts
+++ b/src/scenes/index.ts
@@ -9,6 +9,7 @@ import pure_functions from "./pure_functions?scene";
import valentines_letters from "./valentines_letters?scene";
import birthday_letters from "./birthday_letters?scene";
import sad_people from "./sad_people?scene";
+import generalized from "./generalized?scene";
export const scenes = [
//title,
@@ -20,6 +21,7 @@ export const scenes = [
//hungry_partner,
//pure_functions,
//valentines_letters,
- sad_people,
- birthday_letters,
+ //sad_people,
+ //birthday_letters,
+ generalized,
];