You Don't Know JS
Course Description
Learn to apply functional programming concepts in JavaScript to make your programs more readable and less error-prone! Kyle Simpson will walk you through the core concepts of functional programming like function purity, point-free style, partial-application, currying, composition, immutability, recursion, and list operations like map/reduce/filter. You'll go even deeper with monads and transduction, two more techniques to add to your tool belt!
This course and others like it are available as part of our Frontend Masters video subscription.
Preview
CloseWhat They're Saying
Such a great course by Kyle Simpson on Frontend Masters! Took me 4-5 weeks on weekends to complete. Kyle did a great job explaining FP while also abstracting the complexity so we don't get lost.
Jesse Jafa
jessejafa
I've learned a LOT about functional programming principles and I'd really recommend it if you want to expand your knowledge of functional programming in JavaScript.
Ahmed Elrefaey
a7medev
Course Details
Published: June 18, 2019
Learning Paths
Topics
Learn Straight from the Experts Who Shape the Modern Web
Your Path to Senior Developer and Beyond
- 200+ In-depth courses
- 18 Learning Paths
- Industry Leading Experts
- Live Interactive Workshops
Table of Contents
Introduction
Section Duration: 42 minutes
- Kyle introduces the course on functional programming in JavaScript and explains motivations for creating the course.
- Kyle discusses why it's valuable to learn functional programming and how it enables developers to move from imperative to declarative programming.
- Kyle shares his journey towards learning functional programming, emphasizing, the incremental nature of learning to utilize functional strategies.
- Kyle explains how and why provability is one of the major benefits of functional programming.
- Kyle gives an overview of the course. Topics include: function purity, closure, composition, immutability, recursion, lists/data structures, asynchronous programming, and functional programming libraries.
Function Purity
Section Duration: 1 hour, 14 minutes
- Kyle explains the difference between functions and procedures, giving the requirements for a function keyword element to be a function as opposed to a procedure.
- Kyle demonstrates how functions in functional programming are named based on the semantics of the inputs and outputs of the function.
- Kyle explains why the causes of side effects are indirect inputs and outputs, and explains why they are unavoidable. Kyle also explains how they invalidate the properties of functional programming.
- Kyle continues to refine the definition of pure functions by explaining how constants reduce the purity of functions. Then, Kyle explains how their readability is also harmed by forcing the reader to understand the whole program as opposed to just one line.
- Kyle explains that you should reduce the surface area where constants can be set by passing them in close to where the functions are declared.
- Kyle analyzes why a function is only pure if it isolates the inputs and returns the outputs based on the inputs alone, and not based on anything defined outside the function.
- Kyle analyzes the best way to evaluate the purity of a function, which is to look for areas where the programmer has high confidence, and ones where the programmer has low confidence.
- Kyle discusses how to be obvious about side effects, and how to refactor for function purity by identifying and then extracting or containing it, either moving side effects to the outer shell or reducing their surface area.
- Kyle explains two ways to contain impurity: by using wrapper functions, an impure function wrapped around a pure function, or by using adapter functions, which capture a current state so the state can be restored later.
- Kyle instructs students to refactor functions in order to contain the existing impurity using wrapper functions and adapter functions.
- Kyle live codes the solution to the wrappers section of the exercise.
- Kyle live codes the solution to the adapters section of the exercise.
Argument Adapters
Section Duration: 19 minutes
- Kyle distinguishes between an argument and a parameter, explains what unary and binary functions are, and connects it all by explaining the idea of a function's shape.
- Kyle demonstrates how to change the arguments in a function to shape it, restricting an n-ary function into a unary function as an example.
- Kyle walks through a flip adapter function that flips the arguments passed into another function and gives advice regarding functional libraries like Lodash and Ramda.
- Kyle discusses a common problem with arguments in functional programming where input elements are in an array instead of being individual arguments, and demonstrates how to use the apply function to spread them.
Point Free
Section Duration: 34 minutes
- Kyle describes how equational reasoning can be used to determine whether two functions have compatible shapes, and therefore whether they are interchangeable with each other.
- Kyle walks through the process of defining a function in terms of another function and then converting it to a point-free function, and explains how this can increase code readability.
- Kyle instructs students to refactor three given functions to be point-free.
- Kyle live codes the solution to the exercise.
- Kyle composes two functions into a function that uses currying and composition to demonstrate an advanced point free technique with equational reasoning.
Closure
Section Duration: 1 hour, 6 minutes
- Kyle introduces closure, a function remembering its variables no matter where it is being called, as an essential concept to understand for functional programming. Kyle then discusses how to close over parameters to preserve the purity of a function.
- Kyle instructs students to practice closure by building a string builder utility that makes use of previously closed over variables.
- Kyle live codes the solution to the exercise.
- Kyle explains lazy and eager function execution by giving two code samples, one lazy and one eager, which differ based on when the work for each is done. The benefits and drawbacks of each are discussed.
- Kyle introduces memoization, a technique that holds onto the results of a function to avoid doing the work more than once, and explains how this technique is related to functional purity.
- Kyle explains the final requirement for functional purity, referential transparency, which is when a function call can be replaced by its return value without affecting the rest of the program.
- Kyle discusses function specialization by demonstrating how to create function definitions and function parameter orders that are arranged from general to specific. Kyle explains why this adds readability.
- Kyle introduces two techniques for specializing functions, partial application, where inputs are preset in a series of calls to utilities, and currying, where a function is called with an input a specified number of times.
- Kyle compares partial application and currying, two techniques for function specialization, and explains the distinction between strict currying and loose currying.
- Kyle demonstrates how to use currying to pre-specify one of the inputs to a function in order to change its shape into something potentially more useful.
Composition
Section Duration: 36 minutes
- Kyle introduces composition by defining abstraction as the creation of semantic boundaries. An analogy to a candy factory is used to illustrate the process of drawing these boundaries and applying composition in code.
- Kyle continues using the analogy of the factory to explain what it means for composition to be a method of declarative data flow, with a series of inputs and outputs which flow through a system.
- Kyle discusses what piping is and how it differs from composition, which evaluates from the left to the right as opposed to right to left, and explains its usefulness.
- Kyle instructs students to define their own general compose and pipe functions.
- Kyle live codes the solution to the exercise.
- Kyle explains how the associativity property of composition makes it more useful by enabling currying and partial application on compositions for specialization.
- Kyle discusses the reason why only unary functions are used in composition and then demonstrates how to use currying to create unary functions that can be composed together. Then, Kyle revisits point-free in the context of currying and composition.
Immutability
Section Duration: 54 minutes
- Kyle introduces immutability by defining what it is and what it implies. Kyle then goes over the first of two kinds of immutability that will be focused on throughout the section, assignment immutability.
- Kyle discusses the common confusion with const, which is that the value is immutable, while the only thing that is actually immutable with the const keyword is the variable assignment. The readability of const is put into consideration as a result.
- Kyle argues that the main case for immutability is value immutability, due to the probability that an error with mutability occurred because of a value change and not a reassignment.
- Kyle explains the benefits of using Object.freeze to achieve value immutability on an object and signal to the reader of the code that the object cannot be mutated.
- Kyle recommends that, rather than mutating variables passed by reference, it is better to make a copy instead in case the variable was not originally meant to be mutated.
- Kyle highlights the strengths of immutable data structures, which mutate objects by making copies of the object instead of mutating the original reference while mitigating the practical cost.
- Kyle introduces immutable data structures as a useful tool for when an object needs to be mutated, and explains why this is the case.
- Kyle instructs students to define pure functions dealing with data structures that are not meant to be changed when passed into a function.
- Kyle live codes the solution to the exercise.
Recursion
Section Duration: 1 hour, 6 minutes
- Kyle emphasizes the necessity for functional programmers to understand recursion and proceeds step by step creating a recursive program from an initially iterative problem.
- Kyle offers advice about optimizing recursive operations by changing the location of the base condition, checking to see if there is more work to be done before making the recursive call.
- Kyle instructs students to define a palindrome checker using recursion.
- Kyle live codes the solution to the exercise.
- Kyle analyzes the practicality concerns of recursion, and explains how stack frames are created and memory limits are potentially surpassed when the computer processes recursive calls.
- Kyle explains what tail calls are and how they can potentially solve the problem of a recursive program causing a range error or stack overflow, and argues for its support within the JavaScript language.
- Kyle discusses what proper tail calls are in Javascript and how to make them, including how to initiate strict mode and write the return statement at the end of the function.
- Kyle explains how to tell if something is not in proper tail call form and walks through how to refactor the return statement to be in proper form. Then, Kyle uses curry to store information in a closure to clean the refactored function signature.
- Kyle presents the first strategy for writing recursive algorithms without having to rely on the tail calls optimization, using identity functions. However, Kyle asserts that this is not the best solution in JavaScript because it creates issues with heap memory storage.
- Kyle introduces trampolines, the second and recommended strategy for writing recursive algorithms that don't rely on tail calls. Kyle explains how trampolines allow the call data to be continually made and destroyed, and enables the programmer to write an easily refactorable tail-call function and wrap it in a trampoline.
- Kyle answers questions about what CPS is doing at each step, the issue with CPS in JavaScript vs in other languages, where to get a trampoline utility from, the difference between trampoline calls and regular recursion, and how to wrap a function for trampolining.
List Operations
Section Duration: 1 hour, 9 minutes
- Kyle introduces map, which takes a data structure and maps a transformation across each element, returning a new data structure of the same type with transformed values from the original structure.
- Kyle discusses the filter method, mentioning that filter is an inclusion operation, and not exclusion. Filter is recommended for when there is a collection where values are being kept in or left out of the result.
- Kyle defines reduce as a combination operation, starting with an initial value and generating a resulting discrete value from operating on the elements of the collection using a binary reducer function.
- Kyle proves that reduction can be achieved using composition with the reduceRight function and displays an example.
- Kyle instructs students to practice using list operations by writing three versions of an adding function that take in a list of functions to evaluate.
- Kyle live codes the first part of the exercise solution, two fixed number functions and two add functions.
- Kyle live codes three versions of an addn utility for the exercise solution: iterative, recursive, and reduced.
- Kyle live codes the part of the solution that uses list operations to modify a collection of numbers in an array.
- Kyle discusses fusion, a common situation in functional programming where functional methods are chained, and the practical ramifications of chaining in performance and readability. Kyle demonstrates an instance of fusion using map and compose.
Transduction
Section Duration: 49 minutes
- Kyle introduces transduction as a way to use a mathematical process to reshape map and filter into reducers so that map, filter, and reduce can all be used in conjunction. The transduce and into functions are covered.
- Kyle fields student questions about whether to use the into helper for multiplication, whether to use transduce for sorting, and whether transduce can be classified as a higher-order reducer.
- Kyle begins to derive transduction step by step by performing map and filter using reduce, and eventually extracting reduce from the inside of these two functions and instead using reduce on functions that return a reducer.
- Kyle creates a combiner to use in the two reducer functions and extracts the combiner with currying to increase the specificity of both the map and filter reducer functions.
- Kyle completes the derivation by composing the map and filter reductions, and then turning the remaining two reducers into one by passing sum into the transducer.
- Kyle summarizes the process of deriving transduction, and then fields questions about initial values to reduce, the situation where only map and filter are being used, and how transduction relates to Rx.js.
Data Structure Operations
Section Duration: 53 minutes
- Kyle emphasizes the importance of being able to generalize functional methods to use across any collection or data structure, such as objects and binary trees.
- Kyle instructs students to implement filter and reduce methods for objects.
- Kyle live codes the solution to the exercise.
- Kyle instructs students to refactor code from the previous exercise using advanced point-free techniques.
- Kyle live codes the solution to the exercise.
- Kyle introduces monads, data structures which are wrappers around values which turn the value into a functor, or something that can be interacted with. As an example, Kyle describes the Just monad and its three methods map, chain, and ap.
- Kyle creates a Just monad and a mapping of the monad. Then, Kyle walks through calling map and ap functions on the two created monads, explaining what is occurring at each step.
- Kyle discusses the Maybe monad by walking through code that uses chaining and explains how monads can be useful in performing common programming tasks functionally.
- Kyle fields questions about getting the value out of a monad, how monads are related to math, monad terminology, and how monads are related to category theory.
Async
Section Duration: 17 minutes
- Kyle analyzes how lazy mapping functions and lazy arrays would work, and how functional principles could be adapted to asynchronous programming - turning synchronous and eager operations into asynchronous and lazy operations.
- Kyle defines observables and explains them as being analogous to a spreadsheet involving a lazy, asynchronous flow of data.
- Kyle introduces Rx.js, a library for observables, or time-oriented data structures that allow for achieving functional concepts.
- Kyle instructs students to wire up an observable to create a countdown timer in the console.
- Kyle live codes the solution to the exercise.
Functional JS Utils
Section Duration: 12 minutes
- Kyle introduces Lodash/FP, a module of Lodash with functional methods and gives an example of using the Lodash/FP library.
- Kyle recommends the Ramda functional library for students who do not yet have a functional library preference and then gives an example of using the Ramda library.
- Kyle introduces his FPO library, which is meant to be a similar library to Ramda with a different way of dealing with function signatures: by using a named arguments style.
Wrapping Up
Section Duration: 3 minutes
- Kyle concludes the course by encouraging students to be persistent in the goal to learn functional programming incrementally, adapting code over time.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops