Pattern Glossary

Here is where we introduce all of the patterns we cover in the book and give a brief overview of each. This is a great list to skim if you already have a specific problem you need to solve in a functional way.

Replacing Object-Oriented Patterns

This section shows how to replace common object-oriented patterns with functional language features. This generally cuts down on the amount of code we have to write while giving us a more concise code to maintain.

Pattern 1, Replacing Functional Interface

Here we replace common types of functional interfaces, such as Runnable or Comparator, with native functional features.

This section introduces two basic types of functional features. The first type, higher-order functions, allows us to pass functions around as first-class data. The second, anonymous functions, allows us to write quick one-off functions without giving them a name. These features combine to let us replace most instances of Functional Interface very concisely.

Pattern 2, Replacing State-Carrying Functional Interface

With this pattern we replace instances of Functional Interface that need to carry around some bit of state—we introduce another new functional feature, closures, which lets us wrap up a function and some state to pass around.

Pattern 3, Replacing Command

Replacing Command encapsulates an action in an object—here we’ll take a look at how we can replace the object-oriented version using the techniques introduced in the previous two patterns.

Pattern 4, Replacing Builder for Immutable Object

Here we carry data using the classic Java convention, a class full of getters and setters—this approach is intimately tied up with mutability. Here we’ll show how to get the convenience of a Java Bean along with the benefits of immutability.

Pattern 5, Replacing Iterator

Replacing Iterator gives us a way to access items in a collection sequentially—here we’ll see how we can solve many of the problems we’d solve with Iterator using higher-order functions and sequence comprehensions, which give us solutions that are more declarative.

Pattern 6, Replacing Template Method

This pattern defines the outline of an algorithm in a superclass, leaving subclasses to implement its details. Here we’ll see how to use higher-order functions and function composition to replace this inheritance-based pattern.

Pattern 7, Replacing Strategy

In this pattern we define a set of algorithms that all implement a common interface. This allows a programmer to easily swap out one implementation of an algorithm for another.

Pattern 8, Replacing Null Object

In this pattern we discuss how to replace Null Object and talk about other types of null handling—in Scala, we take advantage of the type system using Option. In Clojure, we rely on nil and some language support to make it more convenient to deal with.

Pattern 9, Replacing Decorator

Replacing Decorator adds new behavior to an object without changing the original class. Here we’ll see how to achieve the same effect with function composition.

Pattern 10, Replacing Visitor

Replacing Visitor makes it easy to add operations to a data type but difficult to add new implementations of the type. Here we show solutions in Scala and Clojure that make it possible to do both.

Pattern 11, Replacing Dependency Injection

This pattern injects an object’s dependencies into it, rather than instantiating them inline—this allows us to swap out their implementations. We’ll explore Scala’s Cake pattern, which gives us a DI-like pattern.

Introducing Functional Patterns

Pattern 12, Tail Recursion

Tail Recursion is functionally equivalent to iteration and provides a way to write a recursive algorithm without requiring a stack frame for each recursive call. While we’ll prefer more declarative solutions throughout the book, sometimes the most straightforward way to solve a problem is more iterative. Here we’ll show how to use Tail Recursion for those situations.

Pattern 13, Mutual Recursion

Mutual Recursion is a pattern where recursive functions call one another. As with Tail Recursion, we need a way to do this without consuming stack frames for it to be practical. Here we’ll show how to use a feature called trampolining to do just that.

Pattern 14, Filter-Map-Reduce

Filter, map, and reduce are three of the most commonly used higher-order functions. Used together, they’re a very powerful tool for data manipulation and are the inspiration for the popular MapReduce data-processing paradigm. In this pattern, we’ll see how they can be used on a smaller scale.

Pattern 15, Chain of Operations

Functional programming eschews mutability; so instead of mutating a data structure, we take one immutable data structure, operate on it, and produce a new one. Chain of Operations examines the differing ways to do so in Scala and Clojure.

Pattern 16, Function Builder

Higher-order functions can create other functions using the Function Builder pattern. Here we’ll show some common instances of the pattern that are built into many functional languages, and we’ll explore a few custom ones.

Pattern 17, Memoization

This pattern caches the results of a pure function invocation to avoid having to do an expensive computation more than once.

Pattern 18, Lazy Sequence

Lazy Sequence is a pattern where a sequence is realized bit by bit only as it’s needed. This allows us to create infinitely long sequences and to easily work with streams of data.

Pattern 19, Focused Mutability

Focused Mutability makes a small critical section of code use mutable data structures to optimize performance. The need for this is less common than you might think. Clojure and Scala, backed by the JVM, provide very efficient mechanisms for working with immutable data, so immutability is rarely the bottleneck.

Pattern 20, Customized Control Flow

With most languages, it’s impossible to add a new way of doing control flow to the language without modifying the language itself. Functional languages, however, usually provide a way to create custom control abstractions tailored for specific uses.

Pattern 21, Domain-Specific Language

The Domain-Specific Language pattern allows us to create a language that is purpose-built for solving a specific problem. Using a well-designed implementation of domain-specific language is the ultimate solution for often-solved problems, as it lets us program close to the problem domain. This reduces the amount of code we have to write and the mental friction in transforming our thoughts into code.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.74.211