Dear Functional Bros
Summary
TLDRThe script discusses the beauty and challenges of functional programming, emphasizing its pure concept of stateless functions and the avoidance of side effects. It explains how functional programming deals with loops and state management through recursion and functions, introducing concepts like currying and lambda functions. The video also demonstrates how functional principles can be applied in JavaScript to create efficient data pipelines, transforming and filtering data in a more declarative manner. The speaker encourages a balanced approach, adopting functional concepts where beneficial without the strict limitations of pure functional programming.
Takeaways
- đ Functional programming emphasizes pure functions with no side effects, ensuring the same output for the same input.
- đ Functional programmers often struggle with marketing their concepts due to the complex terminology like currying, monads, and functors.
- đ Composing functions by connecting their inputs and outputs is a core concept in functional programming, avoiding stateful objects and mutation.
- â Pure functional programming does not allow mutation of variables, making conventional loops like for and while impossible.
- đ Recursion is used in functional programming as a form of iteration, allowing for loops to be expressed as function calls.
- đą The script demonstrates converting a for loop into a series of functional programming constructs like higher-order functions and recursion.
- đ Filtering, mapping, and taking elements from a list are common functional programming operations that can replace traditional loops.
- đ Currying allows for the creation of specialized functions by partially applying arguments, which is useful for creating reusable code patterns.
- đ Functional programming principles have been integrated into popular languages like JavaScript, making it easier to create data pipelines and handle complex operations.
- đ Adopting functional programming principles can lead to more concise and readable code, especially when dealing with data transformations and manipulations.
- đ While pure functional programming has its limitations, its best practices can be applied selectively to improve code quality and efficiency.
Q & A
What is the core concept of functional programming?
-The core concept of functional programming is to write programs with no state, meaning there are no side effects, and the same input always produces the same output.
Why are functional programmers considered bad marketers?
-Functional programmers may be considered bad marketers because they often use complex terms like currying, monads, and functors, which can be difficult for non-experts to understand.
How does functional programming handle loops without using conventional iteration constructs like 'for' or 'while'?
-Functional programming handles loops using recursion and functions, which are designed to perform a specific task repeatedly without mutating state.
What is the purpose of currying in functional programming?
-Currying is a technique in functional programming where a function that takes multiple arguments is transformed into a sequence of functions, each with a single argument. This allows for more flexible and reusable functions.
How does the script demonstrate the use of a 'filter' function in functional programming?
-The script demonstrates the 'filter' function by showing how to pass a predicate (a condition-checking function) to filter elements from a list based on a condition, such as matching a user ID.
What is the 'map' function used for in functional programming?
-The 'map' function is used to transform each element of a list according to a given function, creating a new list with the transformed elements.
How does the script illustrate the creation of a data pipeline in functional programming?
-The script illustrates a data pipeline by chaining together operations such as filtering, mapping, and taking a certain number of elements, which allows for a clear declaration of desired outcomes and simplifies the complexity behind the scenes.
The startup idea aims to address the issue of credit card fraud in restaurants, where the tip and total amounts are manually entered and may not accurately reflect the customer's intention, potentially leading to overcharges.
-null
How does the script suggest functional programming can be beneficial in data-centric jobs?
-The script suggests that functional programming can simplify data-centric jobs by allowing programmers to focus on transforming, filtering, and sorting data in a clear and concise manner, acting as 'sophisticated plumbers' to manage data flows effectively.
What is the script's stance on pure functional programming?
-The script acknowledges that pure functional programming, which prohibits state mutation and side effects, is mostly academic and not practical for real-world computing. However, it highlights that adopting some functional principles can bring significant benefits without the restrictive nature of pure functional programming.
Outlines
đ Introduction to Functional Programming
The paragraph discusses the beauty of functional programming, emphasizing the purity of functions that take inputs and produce outputs without side effects or state. It highlights the challenge of marketing functional programming concepts like currying, monads, and functors, which are complex and lie between mathematical theories and practical language implementations. The speaker acknowledges the difficulty in understanding these concepts but appreciates their elegance. The paragraph also touches on the core concept of functional programming, which is the absence of state, and how this affects common programming constructs like loops and mutation of variables. It introduces the idea of using functions to manage state and the use of recursion as a form of iteration in functional programming.
đ Functional Loops and Currying
This paragraph delves into the specifics of implementing loops in a functional programming paradigm. It explains how to convert a for loop into a series of function calls, using recursion and conditions to mimic the loop's behavior. The speaker introduces the concept of currying, where a function is partially applied by fixing some of its arguments, allowing for more flexible and reusable code. The paragraph also discusses the use of higher-order functions like filter and map, which take other functions as arguments to perform operations on data, and how these can be used to create data pipelines for processing and transforming information.
đ Applying Functional Concepts in JavaScript
The speaker transitions from theoretical concepts to practical applications, showing how functional programming principles can be applied in JavaScript. They demonstrate how to use built-in array methods like map, filter, and sort to create data pipelines that transform and process data. The paragraph also presents a real-world scenario involving a startup that aims to prevent credit card fraud by analyzing restaurant receipts and transactions. The speaker rewrites procedural code into a functional style, showcasing the elegance and efficiency of the functional approach.
đ The Future of Functional Programming
In the final paragraph, the speaker reflects on the current state and potential future of functional programming. They acknowledge that while pure functional programming may be impractical due to the inherent statefulness of computers, the principles of functional programming have been integrated into popular programming languages. The speaker advocates for a balanced approach, adopting functional principles where they make sense without the constraints of a purely functional style. They also speculate on the possibility of functional programming becoming more prevalent in the future, especially in the context of parallel computing and distributed systems.
Mindmap
Keywords
đĄFunctional Programming
đĄCurrying
đĄState Management
đĄRecursion
đĄLambda Functions
đĄHigher-Order Functions
đĄData Pipeline
đĄSide Effects
đĄImmutable Data
đĄPure Functions
Highlights
Functional programming is often misunderstood due to its complex terminology and mathematical roots.
The core concept of functional programming is the purity of functions, which have no side effects and always produce the same output for the same input.
Functional programming avoids state and mutable variables, leading to a different approach to iteration and loops.
Recursion is used in functional programming as a form of iteration, replacing traditional loops.
Functional programming uses functions to manage state and control flow, such as through currying and lambda functions.
Currying allows functions to be created on-the-fly with bound data, similar to object-oriented programming's instance creation.
Functional programming can simplify code by creating data pipelines that filter, map, and transform data.
JavaScript has built-in methods that support functional programming, such as map, filter, and sort.
Functional programming can lead to more concise and readable code, as demonstrated by the transformation of procedural code into a functional pipeline.
The speaker proposes a startup idea, Black Sky Financial, which uses functional programming to detect and prevent credit card fraud in restaurant transactions.
Pure functional programming is often impractical due to the stateful nature of computers, but its principles can be applied selectively for benefit.
Functional programming patterns are becoming more common in modern programming languages, allowing for more efficient data handling and parallel processing.
The speaker encourages functional programmers to focus on the practical benefits of functional programming rather than its complexity.
The transcript ends with a call to action for functional programmers to share their knowledge and help others understand the practical applications of functional programming.
Transcripts
Dear functional bros, I see you.
I hear you.
And I love you.
Functional programing is awesome, but
functional programmers are bad marketers
talking about currying, your monads, binding, functors.
So many words.
I'm not sure anyone truly understands what all these things mean
because they really lie on some spectrum between the math of category
theory, lambda calculus, and their specific mapping
to different language implementations
But still, I do understand the beauty of it.
The concept of a function is so pure.
You have this elegant thing that takes an input
and gives you an output,
and no matter what, the same input
always gives you the same output.
The key thing that ensures that it gives you
the same answer always for infinity is that there's no side effects.
There's no state.
No thing inside of the function
that isn't directly derived by the input.
Once you introduce state, the outcome of the function
can vary based upon that state.
Honestly, most programing
paradigms are really just different takes on how you manage state.
It's all about state.
So let's talk about what functional programing is, why it kind of sucks,
but why adding a little bit to your code is awesome.
Functional programing
takes one extreme side of the state opinion.
It's about writing programs based upon one core concept.
There shall be no state.
You have inputs which are transformed into outputs
in order to get stuff done
you compose and connect functions to other functions,
hooking up their inputs and outputs together into one big long chain
that achieves the goal of the program.
But you don't have objects or structures
in memory that you mutate to track what's going on.
In this absolute pure world where you want to write functions with no state.
This also means that you're not allowed to mutate variables.
So this means if you were to set a value, you cannot change it again.
This means conventional iteration loops like for and while are impossible.
if you think about a for loop or a loop, it requires you to mutate some state,
at least some variable that's tracking how many times you've iterated
So how do you do a loop in a pure functional way?
The answer with functional programing is usually
well, more functions. When all you have is a hammer...
This is the part that we want to repeat over and over again.
So we'll just pull that part out to a function.
So now we need to replicate the three parts of the for loop.
The key thing that the for loop does is increment the index variable
so that the body gets a rerun with each index.
So we need an equivalent of incrementing index
and rerunning our body inside of processReceipt.
Since we can't mutate index, you can imagine us creating
a new variable, next index, which contains the next index
we want to process.
But now we want to repeat this section again.
So we'll need to call process receipt again.
So now if you were to call processReceipt, let's say
with an index of 2
It would print the merchant from index 2
then recall process receipt with index 3
then 4, etc.
but as it is now, it'll keep calling the processReceipt() forever until it goes
beyond the size of the receipt array causing an error to be thrown.
And this is where the second part of the for loop comes into play.
The condition.
We only want to execute the body if the condition is met.
Otherwise we do nothing and move on.
So we'll move that condition down into our function
where we only do anything if our index is still in range.
You can see when we run the program
it works like before.
It increases the index beyond the size of the array
and we still call our function.
But in this
case, it fails our condition and we do nothing.
This breaks the recursive loop and all our functions return
Recursion is just a fancier form of iteration.
And finally, we have our last part of the for loop.
which is where we set our starting point.
This just represents our first call into our recursive loop.
So now we've completely converted our loop to be done in the more functional way,
We can also remove any unneeded variables to make our code more concise.
If we wanted.
Okay, this is pretty simple and just logs each item in the loop.
But what if we wanted to do something useful, like
finding all the receipts that belong to a particular user and return them
so they can be displayed elsewhere?
well, we can take the userId as a third parameter
and then check if the user matches. This
now only prints the receipt of the merchant if the userId.
matches.
But instead we want this function to return the list
of matching receipts so that it can be displayed on the web app.
We need to somehow return the results of the matching. At each recursive call
we want to make an array with the current receipt at the front
and the results from the deeper calls attached to the end.
This way we can get back everything in order.
But we only want to append the current item if it has the right user ID.
Otherwise we just want to pass through the previous result
So, in order to do this
weâll actually get the results of the deeper calls first.
And then if the userId
matches will return the current results appended to the later results.
Otherwise just forward on the later results as is.
And lastly, if we've processed the entire list,
we'll just return empty results since there's no more results to be had.
So now this function just returns all the receipts for a given userId
and we'll give it a better name.
Thing is that you can imagine this pattern happening over and over again
whenever you wanted to find stuff in an array.
The only difference between these functions is the condition in the
if statement.
We could replace all three functions
with just one if we instead passed in a function that returned.
Whether or not an item should be included.
Let's pull out the condition and move it to its own function.
And instead of taking the user idea as a parameter, we'll pass in that function
instead. We can call it condition.
Or if you want to be a classy fellow, you can call it predicate.
Then we just call that function where the condition used to be.
And that function tells us whether or not to include the item.
Then we can pass our condition.
The userIdEquals function into our filter.
And of course, we can now
rename our function to be a generic filter.
Now we can run our beautiful program with our filter and userIdEquals function.
and wait. We have a problem.
Our userIdEquals function takes two parameters
the receipt and the user idea to check against,
but our filter function only checks against the receipt itself.
We don't know the userId to check against.
We could try passing in another value that we could relay into the function.
But what if we need more than one?
Like in the case we needed to check if the total was between
a range, It gets a bit awkward.
So instead we're going to get a bit fancy here.
Instead of having our userIdEquals function, take both a receipt
and a userId,
we're going to have it take only the userId that we want to compare against
and it will construct and return a new function that takes a receipt
and returns whether it's from the userId.
We then pass in that new function that's been created into our filter.
This is a little weird, but what's happening is that the userId
is like a secret extra parameter which is bound to the function.
And this
function remembers that value and can use it.
The name for this pattern is called currying.
Instead of handling the entire operation at once,
it returns a function that handles the next part of the operation
The later part has the previous state bound to it.
That new on the fly created function is what gets called
when filter needs to check a condition.
This is what's a bit funny to me because functional programing
is supposed to be so different than object oriented programing.
But by finding data like this, we're creating an instance of a function
with some bound data to work with.
Instead of creating an instance of a data object
with its bound functions.
Currying like this is a bit of an older way of doing this.
You can automate
this in JavaScript in many other languages by using Bind.
I won't go into bind fully here because really the way
we want to do this today is to use Lambda functions.
This is where we'll move our equals check right
into an inline function.
Now this is finally where things start to get kind of nice.
I'm filtering by user now, or I can filter by merchant just like this.
or do a more complex check on the total here.
We might want to get just a filtered merchant names
instead of the entire object.
If we devise a new function based upon our loop
that doesn't filter based upon a condition,
but instead takes a function that gives you the desired results for each element.
we insert that new transformed element into the array
instead. We'll call this function map
because it maps each element to a different thing.
Then we can change these together.
So first we get our list of receipts.
Find the ones with a total between 14 and 20, and then just say: for each
give us the merchant name.
So now we get an array of the merchant strings
instead of the full receipt objects.
At the end.
And if we only wanted to
take the first five items, we could write a function called Take
Take would give us up to the count elements from the array.
We can chain that on as well.
So now you can see that we basically created a data pipeline here
Where we have an input state, we filter it down to what we want, map
the types of the values to what we want, and then take the first five to display.
Our code clearly declares what we want to happen,
and all the complexity
of how this is done is behind the scenes in our fundamental functions.
So we've just derived these functional style fundamentals ourself,
but these are also built directly into JavaScript.
So let's take a look at how to use those to create data pipelines.
But first, what's our goal with these receipts?
We have this amazing new startup idea
that solves a uniquely American problem in an American way.
In the U.S.
when you're in a restaurant,
you need to fill a tip manually by writing the tip and total.
This is effectively a mandatory fee
on your meal enforced by social shaming.
Your card is initially charged for the total without the tip.
But several days later, the updated total with your hand scribbled tip will show
up on your credit card.
The problem here is that no one is really going to check
whether their tip was accurately reported when their transaction was settled.
So in theory, a company or a disgruntled service staff
could simply enter a bigger number
taking more of your money.
Are you worried about losing your hard earned money to restaurant
credit card fraud?
Black Sky Financial finds these small family owned mom
and pop restaurants and sues them for everything they have.
The proceeds from the destruction of people's dreams
are then equitably distributed to you:
The user of the app based upon how many receipts you've submitted.
Sign up today and start submitting receipts
and know that you're helping prevent credit card fraud in your community!
One lawsuit at a time.
So, yeah, to pull this off, we basically need to grab each receipt,
look up the transaction in the user's connected credit card accounts, filter out
the transactions that haven't yet settled or whose totals match correctly.
Sorting by the most egregious discrepancy and then take the top ten.
Then we display them in a dashboard so our army of lawyers can get to work
fighting the good fight.
Here's that code written in a procedural way.
Let's change this to the functional approach.
In modern JavaScript
all the methods that we need are already built in
and are also methods directly on arrays.
For each receipt.
we eventually want this result object
that contains all of the relevant information:
the receipt, the final transaction, and the discrepancy.
So we can just map our receipts to that.
We can use the built in map method on our array
to transform the array into our list of objects.
The map method takes that lambda function for transforming our receipts
into those result objects.
This condition is skipping over the transactions that aren't yet settled
or don't have a difference
between the receipt total and the final total on the transaction.
So we can just change this to a filter.
We'll need to inverse the condition since it now describes
what to keep instead of what to ignore.
This code basically just ensures that the list is sorted from
biggest to smallest, So we can replace this with a sort on our filter list.
The sort takes a function that tells the sort function
how two elements should be ordered.
It gives you two items and asks for a negative number
if A is less than B and a positive of A is greater than B.
You typically get this by subtracting B from A, but since we want
things ordered big first weâll flip this and subtract A from B,
and then we only want count number of elements
which we can get with the slice method, which we were already doing here.
So we'll just add that into our pipeline And voila.
After we make the formatting a bit more pretty,
all of that is written only in 12 lines.
Functional programing
lets you rewrite things into a beautiful pipeline for your data.
And honestly, most of the programing jobs are really just taking data from Source
A, doing some transformation, filtering, and sorting and then putting it in place
B. A lot of the time we're just sophisticated plumbers.
if you'd like to try out some functional programing like this,
I put some experiments on my website accessible through my Patreon.
I give you some procedural code and ask you to change it
so it doesn't use any for loops or a while loops.
If youâre curious, check them out at CodeAesthetic.io
Dear Functional Bros,
Sometimes I feel like you focus on the complexity
and mathematical elegance of functional programing.
Instead of explaining
why it's awesome and help others see how useful parts of it can be.
Maybe we need a special F bro signal
to let others know that you're also a secret F Bro.
Then you could talk about F Bro things like monads.
But if you don't get the signal, we can play it
chill and talk about how nice it is to delete for loops.
Pure functional programing
where you cannot mutate any state or have any side effects
is kind of awful.
The issue is its fake.
Computers fundamentally have state.
I mean, literally the whole von
Neumann architecture is where you have one giant state in memory
and then little instructions which mutate that state to get stuff done.
Input is non deterministic and any output is forcing some side effect.
Pure functional programing is still mostly academic,
But what has been happening is the best parts of functional programing
have been extracted and injected into our most popular languages.
Like always balance is key.
And adopting some of the principles like reducing state and formulating data
pipelines in your programs where it makes sense can bring huge benefit.
But without all the crazy restrictiveness.
And I'd expect more of these patterns to become more common.
Massively parallel systems don't rely on using one big state of memory.
The more cores you throw at something, the more tracking your state of memory
and elsewhere becomes bottleneck.
So who knows?
Maybe pure functional programing will have a new renaissance.
5.0 / 5 (0 votes)