Clojure is an excellent language for learning Functional Programming. The following courses will guide you through the ideas you’ll need to master Functional Programming. Be sure to click those checkmarks to track your progress.
Calculations are one of the three domains of Functional Programming. They are anything that transform input values to output values. Their results are not dependent on when you run them or how many times you run them. In Clojure, we build calculations from pure functions. Because pure functions don’t depend on time, we can test them whenever we want and as many times as we want. Contrast this to testing sending an email (an Action)–certainly sending a million emails is different from sending one. And so we are very limited in how we test an Action.
Higher-order functions are very important in Functional Programming. They are functions that take functions as an argument. These courses will teach you about the three most common ones: map, filter, and reduce.
3 Functional Tools
Learn these three tools -- map, filter, and reduce-- and you'll be well on your way to developing a functional mindset.
Reduce is the most powerful functional tool available. It lets you build general-purpose recursive solutions without doing the recursion yourself. In this course, we implement reduce and other functions like map and filter using it. This course also goes over some practical things you can do with reduce.
Recursion is an important topic in Functional Programming. And though you may not use it in all functions, it is the main way to write loops in functional languages.
What is recursion? How do you write recursive functions? Does it work with laziness? How is it different from a
for loop? All of these questions are answered, and more, using simple, clear examples. You'll never have fear of recursion again.
Combinators are functions that return other functions. They are typically considered advanced material, but each combinator is not hard to learn on its own. This course goes through several, showing how each is implemented.
Combinators are an important part of functional programming. They are functions -- usually small -- that combine their arguments into new functions. They're great fun and have a lot to teach about functional programming and the lambda calculus. They are an important part of any Clojure programmer's toolkit.
Data is another of the three domains of Functional Programming. Data, by itself, is inert and self-identical (it is what it is). It requires interpretation. For instance, 3kg is a piece of data, but what does it mean? Is it how many tomatoes I want to buy? Or is it the mass of backpack? We use data to represent facts about events in the world.
Clojure uses its immutable collections library extensively. In this course, we dive into the collections, their properties, and idiomatic patterns for using them.
Clojure is based on collections, but how are they used? What are some patterns for making the most of them? This course introduces you to the workhorses of the Clojure programming language, the immutable collections.
Clojure’s sequences are lazy, which is powerful, but it has some drawbacks. This course helps you understand the tradeoffs and how to use laziness to your advantage without getting caught.
Clojure sequences are lazy by default. That gives you big benefits like separation of concerns, but it also brings with it some gotchas. This course is mostly about exploring those gotchas--problems that can bite you if you're not ready for them--and techniques to work with each one. Being prepared is the best antidote to a bad bite. After dealing with the downsides, we explore the big benefits.
This course shows how we can use Data to model interesting properties of our systems.
Data Modeling in Clojure
In Clojure, the common advice is "just use a map". There's some truth to that, but it's obviously more complicated. Clojure gives you lots of ways to model a problem. In this course, I give you a peek behind the curtain. I work step-by-step through different iterations of a domain model, discussing what I'm thinking, why I'm trying something else. We model the game of solitaire, a card game we're all familiar with.
Actions are the third domain in Functional Programming. They represent things that change the world, and are hence bound up in time. They depend on when they are run or how many times they are run. Interestingly, Functional Programming has a lot to say about Actions, probably more than other paradigms that use Actions more.
Clojure’s concurrency primitives are all ways of managing Actions. They are means of safely sharing resources, like mutable state, without getting into a mess.
You've heard that Clojure is great for concurrency. But what tools does Clojure give you? And how should you use those tools?
These lessons are meant to each answer a specific question and help you build the skills you need to address a wide variety of concurrency problems.
Clojure’s core.async library provides another, more sophisticated concurrency primitive that lets us program complex message-passing scenarios with intricate timings.
Learn the fundamentals of core.async, a concurrency library for Clojure and ClojureScript that gives you tremendous power.
Clojure core.async provides basic building blocks for communication and coordination. This course explores ten patterns you can easily implement using those building blocks.
There are some language features that help us program more functionally.
Scoping rules help us manage Data stored in variables. The rules tell us what code has access to which variables.
When you are looking at a variable, how do you know what it refers to? The rules that determine what variable names refer to are collectively called the scoping rules. Learning the three kinds of scope and when to use each will help you make your code more maintainable.
Protocols are an interesting hybrid approach to polymorphism. If you’re used to Object-Oriented Programming, polymorphism is very common. Clojure has type-based polymorphism as well. By using Protocols, we can define common behavior for any Java types, whether they are new or pre-existing.
Protocols are a very cool and very important feature in Clojure. They are a great way to build polymorphism into your software, including extending existing Java classes without modifying them.
Destructuring is a shortcut for assigning values in collections to local variables. It’s often used because we commonly use a lot of collections.
Ever wonder how to read those destructuring forms? Do you want to know how to make your code clearer and shorter? Where can destructuring be used? And how do you construct each one? This course starts from the basics and works through all of the destructuring forms, ending with some examples and advice for using them.