About Me === "For the new faces, I'm Elizabeth, or simponic on the discord..." - I'm 20 years old, graduating this semester once I'm done with my final general class I missed on my grad plan (2credits only, ugh) - I've been enjoying programs functionally for over 3 years; in LISP and Elixir mostly - I was president of the USU Linux club from 2021 - 2024 Part One === "But you didn't come here to meet me; and we don't have much time to get through everything. So let's start. Part one: Flirting With Functions!" Flirting With Functions === Tomorrow's Valentine's day, but you realize; you don't have a Valentine! Desparate to make yourself feel better, you turn to your computer and open Emacs, querying "m-x doctor". ``` I am the psychotherapist. Please, describe your problems. Each time you are finished talking, type RET twice. > i need a valentine Why do you say you might want to have this valentine? > im lonely Are you lonely often? > sometimes Can you elaborate on that? > i need someone or something i can trust What makes you believe you need someone or something you can trust? > i want something that when i ask one question i'll get the > same answer no matter what. ``` What could exist out there that provides this? Let's put a pin in that; it looks like we have a black box here that came out of nowhere. What does it do? When we feed it a one and press a button, it returns one. When we feed it a two, it returns one. A three, two. A four, three. And so forth. No matter how many times we put a number in it gives me the same answer; we're all in love with it already. So we're ready to start getting to know this so called "function". Where could our curiosity take us? Let's look at what's behind this black box. Ah. A simple fibonacci function. ```python def fib(n): if (n <= 2): return 1 return fib(n - 1) + fib(n - 2) ``` We're in love with its predictability, the assurance that no matter what we give as input, the function behaves in a consistent manner, much like the ideal partner who is reliable and trustworthy. But let's imagine, for a moment, a different kind of relationship. One where actions outside the relationship influence your partner's responses. Imagine asking your partner about what food they want to eat. But instead of a straightforward answer based on your question alone and some state (i.e. hunger levels, craving ratios, etc), the function's response is influenced by other factors; the day of the week, and the state of the food they ate the day prior. ```python def randomNumber(): return 4 # picked randomly ``` This unpredictability is what side effects introduce into our programming relationships. Where output is not just determined by its input but also by the state of the outside world, or the system at the time of execution. Suddenly, the predictability we cherished is compromised. So let's take our love of this function and begin studying it. We love our black boxes a lot, and we want to share them with other people in our lives. So let's create another that takes a list of people and creates a custom letter for them. ```python def makeValentinesLetters(people): letters = [] for person in people: letters.append(f"Dear, {person.name}\nYour smile lights up my world. Happy Valentine's Day!") return letters ``` Good! Now they will all share our love. But a few months goes by, and soon all their birthdays are coming up! So we make another black box to generate a letter, and in how many days we should give it to them: ```python def makeBirthdayCards(people): today = new Date() cards = [] for person in people: 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 }) return cards ``` But this is getting annoying; what about Christmas, Thanksgiving, Easter, or another life event such as a wedding? Making this list of new cards and going through each person every single time is getting really tedious. What if we create a bunch of black boxes that take a person and create them a card, specifically. Then we create a black box that takes a list of people and another black box and creates a new card for each person? ```python def valentineLetter(person): return f"Dear, {person.name}\nYour smile lights up my world. Happy Valentine's Day!") def birthdayCard(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 }) 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) ``` Functional Reproduction === After exploring the simple yet profound beauty of our reliable fibonacci function, our journey into the functional programming romance takes an intriguing turn. What's better than one black box the uses a black box? Creating more black boxes. All life on Earth contains instructions in the form of DNA. During mitosis, special mechanisms in our cells read the instructions and create new instructions to give to another cell. Very similarly we can give our black boxes DNA from parents to reproduce and create new black boxes. Let's have a look at an example