00:00 - 00:07
dear functional Bros I see you I hear
00:04 - 00:09
you and I love you functional
00:07 - 00:12
programming is awesome but functional
00:09 - 00:15
programmers are bad marketers talking
00:12 - 00:18
about currying your monads binding
00:15 - 00:20
functors so many words I'm not sure
00:18 - 00:23
anyone truly understands what all these
00:20 - 00:24
things mean because they really lie on
00:23 - 00:27
some spectrum between the math of
00:24 - 00:29
category Theory Lambda calculus and
00:27 - 00:31
their specific mapping to different
00:29 - 00:31
language implementation
00:32 - 00:38
but still I do understand the beauty of
00:34 - 00:40
it the concept of a function is so pure
00:38 - 00:42
you have this elegant thing that takes
00:40 - 00:44
an input and gives you an
00:44 - 00:50
output and no matter what the same input
00:47 - 00:50
always gives you the same
00:51 - 00:55
output the key thing that ensures that
00:53 - 00:58
it gives you the same answer always for
00:55 - 01:01
Infinity is that there's no side effects
00:58 - 01:01
there's no state
01:05 - 01:10
no thing inside of the function that
01:07 - 01:10
isn't directly derived by the
01:13 - 01:17
input once you introduce State the
01:16 - 01:18
outcome of the function can vary based
01:28 - 01:32
state on honly most programming
01:30 - 01:35
paradigms are really just different
01:32 - 01:37
takes on how you manage State it's all
01:35 - 01:40
about state so let's talk about what
01:37 - 01:42
functional programming is why it kind of
01:40 - 01:43
sucks but why adding a little bit to
01:42 - 01:49
your code is
01:50 - 01:55
awesome functional programming takes one
01:52 - 01:57
extreme side of this state opinion it's
01:55 - 02:01
about writing programs based upon One
01:57 - 02:04
Core concept there shall be no State you
02:01 - 02:07
have inputs which are transformed into
02:04 - 02:09
outputs in order to get stuff done you
02:07 - 02:11
compose and connect functions to other
02:09 - 02:13
functions hooking up their inputs and
02:11 - 02:16
outputs together into one big long chain
02:13 - 02:18
that achieves the goal of the
02:16 - 02:20
program but you don't have objects or
02:18 - 02:21
structures in memory that you mutate to
02:20 - 02:24
track what's going
02:21 - 02:27
on in this absolute Pier world where you
02:24 - 02:28
want to write functions with no State
02:27 - 02:30
this also means that you're not allowed
02:28 - 02:32
to mutate variables
02:30 - 02:34
so this means if you were to set a value
02:32 - 02:36
you canot change it again this means
02:34 - 02:39
conventional iteration Loops like for
02:36 - 02:41
and while are impossible if you think
02:39 - 02:43
about a for Loop or while loop it
02:41 - 02:45
requires you to mutate some State at
02:43 - 02:47
least some variable that's tracking how
02:45 - 02:49
many times you've
02:47 - 02:51
iterated so how do you do a loop in a
02:49 - 02:53
pure functional
02:51 - 02:56
way the answer with functional
02:53 - 02:59
programming is usually well more
02:56 - 03:00
functions when all you have is a hammer
02:59 - 03:02
this is the part that that we want to
03:00 - 03:05
repeat over and over again so we'll just
03:02 - 03:06
pull that part out to a function so now
03:05 - 03:09
we need to replicate the three parts of
03:06 - 03:11
the for Loop the key thing that the for
03:09 - 03:13
Loop does is increment the index
03:11 - 03:16
variable so that the body gets rerun
03:13 - 03:18
with each index so we need an equivalent
03:16 - 03:21
of incrementing index and rerunning our
03:18 - 03:23
body inside of process receipt since we
03:21 - 03:26
can't mutate index you can imagine us
03:23 - 03:28
creating a new variable next index which
03:26 - 03:31
contains the next index we want to
03:28 - 03:33
process but now we want to repeat this
03:31 - 03:36
section again so we'll need to call
03:33 - 03:38
Process receipt again so now if you were
03:36 - 03:40
to call Process receipt let's say with
03:40 - 03:45
two it would print the merchant from
03:42 - 03:51
index 2 then recall process receipt with
03:45 - 03:53
index 3 then four Etc but as it is now
03:51 - 03:55
it'll keep calling the process receipt
03:53 - 03:58
forever until it goes beyond the size of
03:55 - 04:00
the receipt array causing an error to be
03:58 - 04:03
thrown and then this is where the second
04:00 - 04:05
part of the for Loop comes into play the
04:03 - 04:08
condition we only want to execute the
04:05 - 04:11
body if the condition is met otherwise
04:08 - 04:12
we do nothing and move on so we'll move
04:11 - 04:15
that condition down into our function
04:12 - 04:17
where we only do anything if our index
04:15 - 04:19
is still in range you can see when we
04:17 - 04:21
run the program it works like before it
04:19 - 04:24
increases the index beyond the size of
04:21 - 04:26
the array and we still call our
04:24 - 04:29
function but in this case it fails our
04:26 - 04:31
condition and we do nothing this breaks
04:29 - 04:34
the recursive Loop and all our functions
04:31 - 04:36
return recursion is just a fancier form
04:36 - 04:40
iteration and finally we have our last
04:38 - 04:42
part of the for Loop which is where we
04:40 - 04:44
set our starting point this just
04:42 - 04:46
represents our first call into our
04:44 - 04:48
recursive Loop so now we've completely
04:46 - 04:50
converted our Loop to be done in the
04:48 - 04:52
more functional way we can also remove
04:50 - 04:54
any unneeded variables to make our code
04:52 - 04:56
more concise if we
04:54 - 04:59
wanted okay this is pretty simple and
04:56 - 05:01
just logs each item in the loop but what
04:59 - 05:03
if we wanted to do something useful like
05:01 - 05:05
finding all the receipts that belong to
05:03 - 05:08
a particular user and return them so
05:05 - 05:09
they can be displayed elsewhere well we
05:08 - 05:12
can take the user ID as a third
05:09 - 05:14
parameter and then check if the user
05:12 - 05:17
matches this now only prints the receipt
05:14 - 05:19
of the merchant if the user ID
05:17 - 05:20
matches but instead we want this
05:19 - 05:22
function to return the list of matching
05:20 - 05:25
receipts so that it can be displayed on
05:22 - 05:27
the web app we need to somehow return
05:25 - 05:29
the results of the matching at each
05:27 - 05:32
recursive call we want to make an array
05:29 - 05:33
with the current receipt at the front
05:32 - 05:36
and the results from the deep recalls
05:33 - 05:38
attached to the end this way we can get
05:36 - 05:40
back everything in order but we only
05:38 - 05:43
want to append the current item if it
05:40 - 05:47
has the right user ID otherwise we just
05:43 - 05:49
want to pass through the previous
05:47 - 05:51
result so in order to do this we'll
05:49 - 05:54
actually get the results of the deeper
05:51 - 05:56
calls first and then if the user ID
05:54 - 05:58
matches will return the current results
05:56 - 06:02
appended to the later results otherwise
05:58 - 06:04
just forward on the later results as is
06:02 - 06:06
and lastly if we've processed the entire
06:04 - 06:08
list we'll just return empty results
06:06 - 06:11
since there's no more results to be had
06:08 - 06:13
so now this function just returns all
06:11 - 06:15
the receipts for a given user ID and
06:13 - 06:17
we'll give it a better
06:15 - 06:19
name thing is you could imagine this
06:17 - 06:21
pattern happening over and over again
06:19 - 06:23
whenever you wanted to find stuff in an
06:21 - 06:26
array the only difference between these
06:23 - 06:28
functions is the condition in the if
06:26 - 06:30
statement we could replace all three
06:28 - 06:32
functions with just one if we instead
06:30 - 06:34
passed in a function that returned
06:32 - 06:36
whether or not an item should be
06:34 - 06:39
included let's pull out the condition
06:36 - 06:40
and move it to its own function and
06:39 - 06:43
instead of taking the user ID as a
06:40 - 06:46
parameter we'll pass in that function
06:43 - 06:47
instead we can call it condition or if
06:46 - 06:48
you want to be a classy fellow you can
06:48 - 06:52
predicate then we just call that
06:50 - 06:54
function where the condition used to be
06:52 - 06:57
and that function tells us whether or
06:54 - 06:58
not to include the item then we can pass
06:57 - 07:01
our condition the user ID equals
06:58 - 07:03
function into our filter and of course
07:01 - 07:06
we can now rename our function to be a
07:07 - 07:11
filter now we can run our beautiful
07:09 - 07:14
program with our filter and user ID
07:11 - 07:16
equals function and wait we have a
07:14 - 07:19
problem our user ID equals function
07:16 - 07:21
takes two parameters the receipt and the
07:19 - 07:23
user ID to check against but our filter
07:21 - 07:26
function only checks against the receipt
07:23 - 07:28
itself we don't know the user ID to
07:26 - 07:30
check against we could try passing in
07:28 - 07:33
another value that we could relay into
07:30 - 07:35
the function but what if we need more
07:33 - 07:37
than one like in the case we needed to
07:35 - 07:40
check if the total was between a range
07:37 - 07:42
it gets a bit awkward so instead we're
07:40 - 07:45
going to get a bit fancy here instead of
07:42 - 07:47
having our user ID equals function take
07:45 - 07:50
both a receipt and a user ID we're going
07:47 - 07:52
to have it take only the user ID that we
07:50 - 07:54
want to compare against and it will
07:52 - 07:56
construct and return a new function that
07:54 - 07:59
takes a receipt and returns whether it's
07:56 - 08:02
from the user ID we then pass in that
07:59 - 08:02
new function that's been created into
08:02 - 08:07
filter this is a little weird but what's
08:05 - 08:10
happening is that the user ID is like a
08:07 - 08:10
secret extra parameter which is bound to
08:10 - 08:16
function and this function remembers
08:13 - 08:17
that value and can use it the name for
08:16 - 08:20
this pattern is called
08:17 - 08:22
currying instead of handling the entire
08:20 - 08:24
operation at once it returns a function
08:22 - 08:26
that handles the next part of the
08:24 - 08:29
operation the later part has the
08:26 - 08:32
previous state bound to it the that new
08:29 - 08:36
on the-fly created function is what gets
08:32 - 08:36
called when filter needs to check a
08:43 - 08:47
condition this is what's a bit funny to
08:45 - 08:48
me because functional programming is
08:47 - 08:50
supposed to be so different than
08:48 - 08:52
object-oriented
08:50 - 08:54
programming but by binding data like
08:52 - 08:57
this we're creating an instance of a
08:54 - 08:59
function with some bound data to work
08:57 - 09:03
with instead of creating an instance of
08:59 - 09:03
a data object with its bound
09:03 - 09:09
functions currying like this is a bit of
09:06 - 09:10
an older way of doing this you can
09:09 - 09:12
automate this in JavaScript and many
09:10 - 09:15
other languages by using
09:12 - 09:17
bind I won't go into bind fully here
09:15 - 09:19
because really the way we want to do
09:17 - 09:21
this today is to use Lambda functions
09:19 - 09:24
this is where we'll move our equals
09:21 - 09:26
check right into an inline
09:24 - 09:29
function now this is finally where
09:26 - 09:31
things start to get kind of nice I'm
09:29 - 09:33
filtering by user now or I can filter by
09:31 - 09:36
Merchant just like this or do a more
09:33 - 09:38
complex check on the total here we might
09:36 - 09:41
want to get just the filtered Merchant
09:38 - 09:43
names instead of the entire object if we
09:41 - 09:46
devise a new function based upon our
09:43 - 09:48
Loop that doesn't filter based upon a
09:46 - 09:50
condition but instead takes a function
09:48 - 09:52
that gives you the desired result for
09:50 - 09:54
each element we insert that new
09:52 - 09:57
transformed element into the array
09:54 - 09:59
instead we'll call this function map
09:57 - 10:01
because it Maps each element to a
10:01 - 10:07
thing then we can chain these together
10:04 - 10:09
so first we get our list of receipts
10:07 - 10:12
find the ones with a total between 14
10:09 - 10:14
and 20 and then just say for each give
10:12 - 10:14
us the merchant
10:15 - 10:19
name so now we get an array of the
10:18 - 10:21
merchant strings instead of the full
10:19 - 10:24
receipt objects at the
10:21 - 10:25
end and if we only wanted to take the
10:24 - 10:28
first five items we could write a
10:25 - 10:31
function called take take would give us
10:28 - 10:34
up to the count elements from the array
10:31 - 10:36
we can chain that on as well so now you
10:34 - 10:38
can see that we basically created a data
10:36 - 10:41
pipeline here where we have an input
10:38 - 10:43
State we filter it down to what we want
10:41 - 10:46
map the types of the values to what we
10:43 - 10:49
want and then take the first five to
10:46 - 10:51
display our code clearly declares what
10:49 - 10:53
we want to happen and all the complexity
10:51 - 10:54
of how this is done is behind the scenes
10:53 - 10:57
in our fundamental
10:54 - 11:00
functions so we've just derived these
10:57 - 11:02
functional style fundamentals ourselves
11:00 - 11:05
but these are also built directly into
11:02 - 11:07
JavaScript so let's take a look on how
11:05 - 11:10
to use those to create data
11:07 - 11:11
pipelines but first what's our goal with
11:11 - 11:15
receipts we have this amazing new
11:13 - 11:18
startup idea that solves a uniquely
11:15 - 11:20
American problem in an American Way in
11:18 - 11:23
the US when you're in a restaurant you
11:20 - 11:24
need to fill a tip manually by writing
11:24 - 11:29
total this is effectively a mandatory
11:26 - 11:31
fee on your meal enforced by social
11:29 - 11:33
shaming your card is initially charged
11:31 - 11:35
for the total without the tip but
11:33 - 11:37
several days later the updated total
11:35 - 11:38
with your hand scribble tip will show up
11:37 - 11:40
on your credit
11:38 - 11:42
card the problem here is that no one is
11:40 - 11:44
really going to check whether their tip
11:42 - 11:47
was accurately reported when their
11:44 - 11:49
transaction was settled so in theory a
11:47 - 11:50
company or disgruntled service staff
11:49 - 11:52
could simply enter a bigger number
11:50 - 11:54
taking more of your money are you
11:52 - 11:56
worried about losing your hard-earned
11:54 - 11:58
money to restaurant credit card fraud
11:56 - 12:00
black Sky Financial finds these small
11:58 - 12:03
family-owned mom and popop restaurants
12:00 - 12:05
and Su them for everything they
12:03 - 12:07
have the proceeds from the destruction
12:05 - 12:09
of people's dreams are then equitably
12:07 - 12:12
distributed to you the user of the app
12:09 - 12:14
based upon how many receipts you've
12:12 - 12:15
submitted sign up today and start
12:14 - 12:17
submitting receipts and know that you're
12:15 - 12:20
helping prevent credit card fraud in
12:17 - 12:23
your community one lawsuit at a
12:20 - 12:25
time so yeah to pull this off we
12:23 - 12:26
basically need to grab each receipt look
12:25 - 12:29
up the transaction in the user's
12:26 - 12:30
connected credit card accounts filter
12:29 - 12:33
the transactions that haven't yet
12:30 - 12:35
settled or whose totals match correctly
12:33 - 12:38
sort them by the most egregious
12:35 - 12:39
discrepancy and then take the top 10
12:38 - 12:41
then we display them in a dashboard so
12:39 - 12:43
our army of lawyers can get to work
12:41 - 12:45
fighting the good
12:43 - 12:48
fight here's that code written in a
12:45 - 12:51
procedural way let's change this to the
12:48 - 12:52
functional approach in modern JavaScript
12:51 - 12:55
all the methods that we need are already
12:52 - 12:58
built in and are also methods directly
12:55 - 13:00
on arrays for each resit we eventually
12:58 - 13:02
want want this result object that
13:00 - 13:04
contains all of the relevant information
13:02 - 13:05
the receipt the final transaction and
13:05 - 13:10
discrepancy so we can just map our
13:07 - 13:12
receipts to that we can use the built-in
13:10 - 13:15
map method on our array to transform the
13:12 - 13:17
array into our list of objects the map
13:15 - 13:19
method takes a Lambda function for
13:17 - 13:21
Transforming Our receipts into those
13:22 - 13:27
objects this condition is skipping over
13:25 - 13:28
the transactions that aren't yet settled
13:27 - 13:30
or don't have a difference between the
13:28 - 13:32
re seip total and the final total on the
13:30 - 13:33
transaction so we can just change this
13:33 - 13:37
filter we'll need to inverse the
13:35 - 13:40
conditions since it now describes what
13:37 - 13:43
to keep instead of what to
13:40 - 13:45
ignore this code basically just ensures
13:43 - 13:47
that the list is sorted from bigest to
13:45 - 13:49
smallest so we can replace this with a
13:47 - 13:51
sort on our filtered list the sort takes
13:49 - 13:54
a function that tells the sort function
13:51 - 13:55
how two elements should be order it
13:54 - 13:58
gives you two items and asks for a
13:55 - 14:00
negative number if a is less than b and
13:58 - 14:02
a positive if a is greater than b you
14:00 - 14:05
typically get this by subtracting B from
14:02 - 14:07
a but since we want things ordered big
14:05 - 14:10
first we'll flip this and subtract a
14:07 - 14:12
from B and then we only want Count
14:10 - 14:14
number of elements which we can get with
14:12 - 14:17
the slice method which we were already
14:14 - 14:19
doing here so we'll just add that into
14:17 - 14:22
our Pipeline and
14:19 - 14:24
voila after we make the formatting a bit
14:22 - 14:27
more pretty all of that is written only
14:24 - 14:28
in 12 lines functional programming lets
14:27 - 14:31
you rewrite things into a beautiful
14:28 - 14:33
pipeline for your data and honestly most
14:31 - 14:35
of programming jobs are really just
14:33 - 14:38
taking data from Source a doing some
14:35 - 14:40
transformation filtering and sorting and
14:38 - 14:42
then putting it in place B A lot of the
14:40 - 14:44
time we're just sophisticated
14:42 - 14:46
plumbers if you'd like to try out some
14:44 - 14:48
functional programming like this I put
14:46 - 14:50
some experiments on my website
14:48 - 14:51
accessible through my patreon I give you
14:50 - 14:53
some procedural code and ask you to
14:51 - 14:55
change it so it doesn't use any for
14:53 - 14:57
Loops or while Loops if you're curious
14:55 - 15:00
check them out at COD athetic
15:00 - 15:04
dear functional
15:01 - 15:06
Bros sometimes I feel like you focus on
15:04 - 15:08
the complexity and mathematical Elegance
15:06 - 15:10
of functional programming instead of
15:08 - 15:13
explaining why it's awesome and help
15:10 - 15:15
others see how useful parts of it can be
15:13 - 15:17
maybe we need a special fpr signal to
15:15 - 15:18
let others know that you're also a
15:18 - 15:22
fpro then you could talk about fpro
15:22 - 15:26
monads but if you don't get the signal
15:24 - 15:30
we can play a chill and talk about how
15:26 - 15:32
nice it is to delete for loops
15:30 - 15:34
pure functional programming where you
15:32 - 15:37
cannot mutate any state or have any side
15:34 - 15:39
effects is kind of awful the issue is
15:37 - 15:41
it's fake computers fundamentally have
15:39 - 15:43
state I mean literally the whole Von
15:41 - 15:46
noyman architecture is where you have
15:43 - 15:48
one giant state in memory and then
15:46 - 15:50
little instructions which mutate that
15:48 - 15:52
state to get stuff done input is
15:50 - 15:55
non-deterministic and any output is
15:52 - 15:58
forcing some side effect pure functional
15:55 - 15:59
programming is still mostly academic but
15:58 - 16:01
when what has been happening is the best
15:59 - 16:03
parts of functional programming have
16:01 - 16:04
been extracted and injected into our
16:03 - 16:07
most popular
16:04 - 16:09
languages like always balance is key and
16:07 - 16:11
adopting some of the principles like
16:09 - 16:12
reducing State and formulating data
16:11 - 16:14
pipelines in your programs where it
16:12 - 16:17
makes sense can bring huge benefit but
16:14 - 16:18
without all the crazy restrictiveness
16:17 - 16:21
and I'd expect more of these patterns to
16:18 - 16:23
become more common massively parallel
16:21 - 16:26
systems don't rely on using one big
16:23 - 16:27
state of memory the more cores you throw
16:26 - 16:30
at something the more tracking your
16:27 - 16:33
state of memory and elsewhere becomes a
16:30 - 16:36
bottleneck so who knows maybe pure
16:33 - 16:45
functional programming will have a new