Episode Transcript
Available transcripts are automatically generated. Complete accuracy is not guaranteed.
Jim (00:03):
Welcome to another episode
of Runtime Arguments.
I'm Jim McQuillen and my partnerhere is Wolf.
Hello.
Thanks, Wolf.
We have got an awesome episodefor you today.
We're going to be talking aboutfunctional programming.
This is something that I've beenkind of confused about for a
while.
And uh Wolf, this is one whereWolf is doing the research for,
(00:27):
and he's got some great stuff totalk about.
I'm really excited to get intoit.
We're gonna get going right now.
You ready, Wolf?
Wolf (00:37):
I'm ready.
Um let me start with a littlebit about Jim and me.
Uh we're both, there's lots ofdifferent words for it.
Software engineers, programmers,coders, whatever.
That's what we do.
We write code all day.
And we have languages that weuse primarily.
Jim's a Perl guy and someJavaScript and some Swift.
(01:00):
I'm a Python guy and some Rust,and I've done C and PHP in the
past.
Um the kind of programming thatwe do might be called
procedurals or maybeobject-oriented, or, you know,
there's uh a couple differentnames for it.
But there are languages that yousee sometimes uh and people talk
(01:25):
about.
Um I'm going to talk a littlebit about them.
Um, and these languages arelabeled functional.
And when you try to talk tosomebody who knows about them,
they start saying things thatare complicated and mathematical
and seem like theorems, and andit's just a huge gatekeeping
(01:47):
thing.
Like I I feel like I'm a goodprogrammer and and that I'm, you
know, reasonably intelligent.
Uh, and they say things that arecompletely incomprehensible to
me.
I feel like I can't know orunderstand what functional
programming is.
And I wanted to know.
So I spent some time f I spentsome time finding out what it's
(02:12):
all about.
Uh it's not just for academicsor mathematicians.
Uh the truth about functionalprogramming is you probably
already understand the mostcomplicated, hardest parts of
it, and you're probably alreadyusing those things in the modern
languages that you are usingtoday.
(02:33):
Um we're gonna strip away allthat jargon and show you what
functional programming actuallyis, why it's a good idea for
many situations, and how you canuse it better.
So let me start with um wherethis all came about.
(02:54):
In 1958, um the grandmother offunctional languages, Lisp, um,
everything's a list, andeverything is a function.
Uh and from there, thingsdeveloped.
In the 1970s was a languagecalled ML that introduced a
(03:15):
thing called type inference.
In 1987, um Erlang came along uhthat was uh designed and built
by Ericsson and ran phonesystems that had 99 and some
huge number of 9% uptime.
Uh in 1990, Haskell.
(03:37):
Um what if everything wasfunctional, is Haskell's
thought.
Uh in the 2000s, we gotlanguages more for human beings,
like Scala, Clojure, F sharp, Fsharp's Microsoft's thing.
Um you have probably seen thesethings around.
Uh the other languages I justmentioned, you probably see
(03:57):
less.
And there is a modern descendantof Erlang, and that's Elixir.
Um, Elixir runs on the Erlangvirtual machine.
Um so uh these are some of thelanguages that are functional.
Jim (04:16):
So back up a second.
You you're telling me Erlang wasrunning phone systems?
I I I thought it was justacademic.
Wolf (04:26):
No.
Erlang turns out, I mean, it waswritten by a company um
specifically for this job andspecifically to be robust.
Um, you know, uh languages thatare designed by companies um for
their own hardware, uh, we seethat all the time.
(04:47):
Like Apple and Swift, forinstance.
But uh WhatsApp handled 900million users with just 50
engineers using Erlang.
It Erlang's a real worldlanguage.
Um let me talk about some coreconcepts.
Um functional, because thelanguages you you're using right
(05:11):
now, they're not calledfunctional languages.
Most modern languages are uhmulti-paradigm.
Uh they're hybrids.
They have functional things.
So what makes code functional?
Um a couple things, some ofwhich you probably do use, and
(05:32):
some of which you probably don'tuse.
One thing is pure functions.
A pure function has no sideeffects.
You put in a number orsomething, whatever, and the
answer comes out.
If you put in the same set ofparameters, the same answer
comes out.
It doesn't depend on anythingelse, like it doesn't check the
(05:53):
weather.
If your function adds twonumbers together and you give it
two and two, it produces fourevery single time.
That's a pure function.
Um there's downsides to purefunctions.
If you don't have side effects,you uh you can't write to a
database, you can't uh delete afile, you can't update some
(06:16):
global variable.
Anyway, uh a second factor offunctional code is immutability,
especially immutability bydefault.
That means your variables oryour data structures or whatever
don't change.
Um this is very unlike uh a lotof code that we write.
(06:39):
Um some languages have actuallyadopted this, and it's a a
really strange shift when youmove to it.
But like Rust.
In Rust, variables aren'tvariable.
They are immutable by defaultunless you say something.
Um the third thing is functionsare first class.
(07:03):
You can pass a function as avariable, a function can return
another function as a result.
Um these three big things ummake up what is functional
programming.
Jim (07:21):
So I I I've been hearing
for a long time that functional
programs don't have side effectsin your functions.
That's uh I'm I'm writingprograms all the time that have
to change data.
They update databases.
I'm writing businessapplications.
Read data out of a database,modify it, and and update it.
(07:41):
Uh how does that work in thisparadigm?
Wolf (07:46):
There are two different um
paths along which data gets
changed or feels like it'schanged.
Um of those paths is that a lotof these languages that are
labeled functional actually aredivided into two sets of
(08:11):
functionality.
Um side is pure, and the otherside is the thing that reaches
out to databases and whatnot.
Um and that's often the way youwill write these programs if
you're using uh a more modernlanguage like Python or Rust or
whatever.
Um the other path is somethingthat you see all the time.
(08:35):
Um you take in a data structureand you give back a new data
structure that looks a lot likethe old one, but with your
changes.
And it feels like you've changedthe data, but really it's a
brand new thing.
Just like in Git, when you add anew commit, yeah, the code is
(08:58):
different now, uh, but youdidn't change any of the old
commits, you just added a newone on top.
Um so that's how a lot of thesefunctional languages work.
And modern multi-paradigmlanguages don't have to worry
about being purely functional.
(09:19):
They've got data mutation builtin, they know how to modify
things.
Um let me talk a little bitabout functional programming
syntax that you're alreadyusing.
Um I'm gonna bring up a coupledifferent languages, and this is
why I started off by talkingabout uh the languages that Jim
(09:42):
and I write write code in.
Um I write a lot of Python, andone of the things that is used a
lot in Python uh iscomprehensions, especially list
comprehensions.
There there are different kindsof comprehensions, but a list
comprehension is the mostpopular.
(10:03):
And a list comprehension, I'mgonna say it in the most basic
instance of a listcomprehension, takes a list and
gives you a new list.
The action in a listcomprehension changes, produces
(10:24):
a new and different value foreach value in the input list,
and the output list is a list ofthose result values.
In JavaScript, um there's a tonof array methods like dot map
and dot filter and dot reduce.
All of those are functionalprogramming.
(10:46):
JavaScript promise changechains?
Yeah.
Um I I don't want to leave Jimout.
Modern Perl has a bunch offunctional programming stuff in
it.
Um Perl uh gets uh I don't know,are they called packages, Jim?
Yeah.
Um so Pearl has list colon colonutil, which gives you reduce any
(11:12):
all first.
Um higher there's uh a bookcalled Higher Order Pearl uh
that talks about functionalprogramming.
Uh l uh Pearl has closures.
Um Pearl from the start hadfunctional powers.
Jim (11:30):
So when Larry Wall designed
Pearl, he included functional
concepts?
Wolf (11:36):
Yeah.
Larry Wall uh is a linguist.
He took the best ideas fromeverywhere.
Pearl's motto, uh there's morethan one way to do it, included
functional waves from day one.
You've been doing functionalprogramming since your very
first map block.
Uh I used map today.
(11:59):
Um I have been exploring Rust,and um, you know, when I first
came into Rust, I was incrediblydissatisfied because it was
missing all kinds of things thatI thought it needed.
It doesn't have null or none, itdoesn't have exceptions, um, I
(12:20):
didn't see, but it turns outRust has option and Swift has
optional, and C sharp hasnullable types.
And um this is where it getsfun.
Uh all of those things that Ijust named are almost um one of
(12:43):
the gosh, it's it's socomplicated, it's practically a
joke among uh the people who dofunctional programming.
Um those things are almostmonads.
Um but you already understandthose things.
Uh option is just a box thateither has something or not.
(13:05):
Um that's a little bit differentthan uh a pointer that might be
null or a list that might beempty.
Um it's just a little bitdifferent.
Um, but it is different.
Jim (13:19):
Wait, so monads are just
option types?
Wolf (13:24):
Uh monads are the pattern
behind options and results and
promises and even lists.
But here's the secret (13:31):
you don't
need to understand monads or
monad theory or any of thiscomplicated gatekeeping crap.
Uh you already know how to usethese things perfectly.
I mean, if you're a Rustprogrammer, you know how to use
Option.
If you're a Pearl programmer,you know, you know what I'm
saying.
Jim (13:51):
Sure, sure.
Um if you really want to meltyour brain, uh take a look at
the monads page on Wikipedia.
It's scary to look at.
Uh I'm still feeling the effectsof what I saw there.
Uh and it leads to other pagesthat are equally scary.
Uh, I I it's I don't understandwhy there's that much about
(14:17):
monads that it's that hard tounderstand when in reality uh
Wolf just explained they'rethey're they're I mean optionals
are monads and other things aremonads, but I don't know, still
scary to me.
Wolf (14:35):
They're kind of like
Schrdinger's cat.
There's a box, and eitherthere's something in it, or
maybe there's nothing in it.
Or maybe there's somethingtotally different in it.
Um don't open the box.
Anyway.
Don't open the box.
So functional programming um hasbeen a foundation of uh
(14:57):
languages that we've been usingin the past, and people who
design programming languageshave seen that it does good
things, and so it's gettingadopted as people write brand
new or grow existing languages.
For instance, uh Java 8 streams.
(15:19):
Um Java basically wentfunctional in 2014.
User streams, filter active, mapthe emails, collect the list.
Uh Python has uh more and morefunctional programming features.
Uh you can see the things initer tools, func tools, the
brand new match statement, umtype hints, making result types
(15:42):
possible.
Um Rust is uh incredible.
Uh it it made immutability thedefault.
You have to ask permission tomutate.
Result type makes error handlingexplicit and unavoidable.
Um it proves FP concepts work insystems programming.
Jim (16:05):
So basically, every
programming language is becoming
functional.
Wolf (16:10):
Yeah.
Modern languages um aremulti-paradigm.
Uh they let you do uh basicallywhatever approach solves the
problem you are facing.
And that's what these languagesare for in the first place.
They're to solve problems.
Um so providing more and moretools to solve problems, that
(16:33):
sounds like the right answer tome.
Uh like every interesting kindof technique that you use in
programming, um functionalprogramming is good at certain
kinds of problems, um like datapipelines, transforming CSVs, uh
processing logs, um, things likethat.
(16:55):
Um concurrent code.
Uh if you have immutable data,then concurrency is easy.
You don't need locks, um,financial calculations, uh,
because um functional code isreally easy to test, it's very
auditable, there's no surprises.
(17:17):
Um, web requests, that's whypromises work the way they do.
Um there's a lot of real-worldwins using functional
techniques.
Netflix processes billions ofevents with functional streams.
Banks love functionalprogramming because bugs cost
millions of dollars.
(17:38):
Discord switched to Rust for thefunctional guarantees.
Um but you don't need uh to useLisp to get these powers.
Uh you can use functionaltechniques in your own code
right now.
Um here's a couple things youcan do.
Um parse.
(17:59):
Don't validate.
Validate email once, create anemail type, trust it everywhere.
Instead of throwing exceptions,returning success or failure, uh
a Python example, uh return atuple of success and uh value or
an error.
Uh make invalid statesimpossible to express.
(18:23):
Don't use strings for status,use separate types.
Um you can't accidentally shipan unpaid order if they're
different types.
Um pipeline your logic, chainoperations together instead of
nesting them, and then eachfunction in the chain does just
one thing.
Jim (18:44):
All right, I'm I'm still
confused.
Um I I I don't quite understandit.
Can you walk us through anexample of of just what you're
talking about?
Wolf (18:56):
Absolutely.
Um I'll I'll give you theclassic example um having to do
with um regional sales data.
Um so let me tell you the beforeand the after.
Um so here's what I used towrite, and and I'll bet you've
seen this before, maybe evenwritten it before.
(19:18):
Um I'd start with an emptydictionary for the results, I'd
loop through all the salesrecords inside that loop, check
if the sale is completed.
If it's not, skip it, you know,continue, whatever.
If it is, check if we've seenthis region before.
If not, initialize that regionin our dictionary to zero, then
(19:44):
add that sales amount to theregion total, and I probably
need error handling in the casethat the amount field is
missing.
By the time I'm done, I've gotnested loops, multiple if
statements, mutation everywhere,and good luck unit testing this
without mocking.
The entire database.
Jim (20:02):
That sounds like every
reporting function I've ever
written.
Wolf (20:06):
Alright.
Let me tell you a better way.
Here's the functional approach.
Take the sales data, filter tojust completed sales.
Group by region.
Sum the amounts for each group.
(20:27):
Done.
Each little thing that I saidthere is one function.
Each of them takes input fromthe function before and passes
it, passes the their output,their result, to the function
that comes after.
(20:57):
It would be one expression.
It's easy to test.
It's easy to prove.
It's ridiculous.
Jim (21:12):
Is it actually shorter and
cleaner when you do that?
Wolf (21:15):
It is.
It's about half the lines.
But more importantly, in thefunctional version, each step it
either works or it doesn't.
In the imperative version, Imight forget to initialize a
region or accidentally doublecount or mutate the wrong
variable.
The functional version makesthose bugs impossible.
To test the imperative version,I need to set up the entire
(21:39):
environment, track mutations,and verify intermediate states.
To test the functional version,first I test the filter.
Given sales, does it return onlyone com only completed ones?
Test the grouping.
Given sales, does it group byregion correctly?
Test the sum.
Given amounts, does it addcorrectly?
(21:59):
Each test is trivial becauseeach function does one thing.
SPEAKER_02 (22:06):
So it's cleaner and
it's more testable.
Wolf (22:09):
Exactly.
And here's the kicker.
If tomorrow they say we alsoneed to exclude refunds, where
do I change the code?
In the functional version, I'dadd one more filter step.
In the imperative version, I'madding another if statement
somewhere in those nested loopsand hoping to God I put it in
the right place.
Jim (22:45):
I think that would be kind
of crazy.
But when I write SQL, I sort ofwrite it in a functional style,
I think.
I start off with what is ourbasic data.
So there's my select, right?
I I select a bunch of data outof a table.
And then they they want tofilter it.
So I mean I have a where clause,but sometimes I need to
(23:07):
basically wrap that uh selectstatement in another select.
So my first one is a sub-select,a subquery.
So in that outer query, I'mfiltering or grouping or doing
something, and then often I'llwrap it again with another uh
select.
So so I've got like twosubqueries, and that's kind of
(23:30):
doing what you just said.
When I need to make a change,there's a certain place in that
chain of uh queries uh that Imake my change.
So I I guess I'm doing somefunctional programming in SQL.
Does does that make sense?
Wolf (23:44):
It uh it kind of feels
like you are.
Like my SQL is not nearly asgood as yours.
In mine, instead of making amore complicated um query, I'd
probably make temp tables andhave little queries that moved
data from one table to the next.
(24:06):
Um, but I think uh you doing itin the query is is exactly the
same as me doing temp tables.
Jim (24:15):
Uh I think, I believe that
by me doing it all with in
nested queries, uh, it allowsthe query optimizer to do its
thing.
And it might flatten some ofthose nested queries.
It does all kinds of magic.
I I use Postgres and it's got apretty good query optimizer, and
I think my solution would befaster than yours.
Wolf (24:36):
Oh, I'm sure it would be.
I definitely trust your SQL morethan I trust my SQL.
I mean, I'm okay.
I can solve the problem, but uhyou you've been at it a lot
longer than me.
That's my feeling.
Um let me tell you uh where youcan start, what you should do to
(25:03):
understand this stuff better.
You don't need to learn Haskell,you don't need to understand
category theory, you don't needto read academic papers.
Here's what you should do (25:15):
use
map, filter, reduce, uh, instead
of loops, when it's cleaner.
Um I'm absolutely not tellingyou to make your code less
understandable, because to me,clear code is one of the highest
(25:35):
goals.
Uh but if you can use one ofthese functions instead of a
loop, and it is the right thing,you should.
Um if you're using Rust, uh youknow about result.
If you're not using Rust, see ifyou can use Rust's result
pattern in your language.
(25:57):
Um take a class that you use, umI don't know what language
you're using, but it probablyhas something that is a class or
is like a class.
Take a class like that and makeit immutable.
Um for instance, um, if you'reworking with geometry, um why
(26:18):
are points mutable?
Why should I be able to changethe X in a point?
Um why not, when I move a point,just return a new point?
Points are probably smallanyway, that seems easy to me.
Um try writing some purefunctions for your business
logic.
SPEAKER_02 (26:38):
Um Yeah?
Okay, what if I do want to godeeper?
Wolf (26:46):
Well, if if you want to uh
l use a language that actually
has functional features, uh evenif you're not trying to write a
a real program, you just want toplay around, uh give Rust a try
or Elixir.
Um they're both pretty prettyfriendly.
(27:08):
Um or just keep writing Python,JavaScript, Java, Perl, but in a
functional style.
Um I think the takeaway here isthat whatever you're doing now,
almost certainly, you're alreadyfunctional.
Every time you write a listcomprehension in Python, every
(27:31):
time you use option in Rust,every time you chain promises in
JavaScript, you're doingfunctional programming.
Uh the question isn't whether tolearn functional programming,
you're already using it.
The question is, what if you didit on purpose?
Um, your homework.
(27:51):
Find one ugly function full ofmutations and exceptions.
Try making it pure.
Return results instead ofthrowing.
Make the data immutable.
I guarantee it'll be easier totest and harder to break.
SPEAKER_02 (28:08):
So that's it.
I'm already a functionalprogrammer.
Yes, you are.
Now go be a better one.
Challenge accepted.
Jim (28:18):
All right, that was an
excellent uh little uh tutorial
on uh functional programming.
Uh, as always, you can contactus at feedback at
runtimearguments.fm.
Uh more info is in the shownotes, including uh additional
ways to contact us.
And as always, thank you so muchfor listening.
Wolf (28:40):
Hi, everybody.