**Preface**

This chapter covers

To understand how functional programming works, we could use functional components provided by some functional library, or even the few that have been made available in the Java 8 library. But instead, we’ll look at how you can construct things rather than how to use these provided components. Once you’ve mastered the concepts, it will be up to you to choose between your own functions and the standard Java 8 ones, or to rely on one of the existing external libraries.

**In this chapter you’ll create a Function very similar to the Java 8 Function. It will be a bit simplified in how it handles type parameters**(avoiding wildcards)

**in order to make the code easier to read, but it will have some powerful capacities that are absent from the Java 8 version.**Apart from those differences, they’ll be interchangeable.

You might have trouble understanding some parts of the code presented in this chapter. That’s to be expected, because it’s very difficult to introduce functions without using other functional constructs such as

**List**,

**Option**, and others. Be patient. All the unexplained components will be discussed in the following chapters. I’ll now explain in greater detail what a function is, both in the real world and in a programming language.

**Functions aren’t only a mathematical or programming entity. Functions are part of everyday life. We’re constantly modeling the world in which we live, and this is true not only for programming. We construct representations of the world around us, and these representations are often based on objects that mutate their state as time changes**. Seeing things this way is human nature. Going from state A to state B takes time, and it has a cost in terms of time, effort, or money.

Consider addition as an example. Most of us see it as

**a computation that takes time**(and sometimes intellectual effort!). It has

**a starting state**,

**a transition**(the computation), and

**a resulting state**(the result of the addition). To add 345, 765, and 34,524, we certainly need to perform a computation. Some of us can do it in little time, and others will take longer. Some might never succeed, or will get an erroneous result. Some will make the computation in their head; others will need to write it down on paper. All will probably mutate some state to achieve this, whether it’s a sheet of paper or some part of their brain. But to add 2 and 3, we don’t need all this. Most of us have memorized the answer and can give the result immediately, without doing any computation.

This example shows that computation isn’t the essential element here. It’s just a means to calculate the result of a function. But this result existed before we made the computation. We just generally don’t know what this result is beforehand.

**Functional programming is just programming using functions. To be able to do this, we first need to know what a function is, both in the real world and in our programming language of choice**.

**What is a function?**

**A function is generally known as a mathematical object, although the concept is also ubiquitous in everyday life**. Unfortunately, in everyday life, we often confuse functions and effects. And what is even more unfortunate is that we also make this mistake when working with many programming languages.

**Functions in the real world**

**In the real world, a function is primarily a mathematic concept**.

**It’s a relation between a source set, called the function domain, to a target set, called the function codomain**. The domain and the codomain need not be distinct. A function can have the same set of integer numbers for its domain and its codomain, for example.

**What makes a relation between two sets a function**

To be a function, a relation must fulfill one condition: all elements of the domain must have one and only one corresponding element in the codomain, as shown in figure 2.1.

**Figure 2.1. All elements of a function’s domain must have one and only one corresponding element in the codomain.**

This has some interesting implications:

You can, for example, define the function

- f(x) = x + 1

*x*is a positive integer. This function represents the relationship between each positive integer and its successor. You can give any name to this function. In particular, you can give it a name that will help you remember what it is, such as

- successor(x) = x + 1

- predecessor(x) = x + 1

Note that we’re talking about what a function is (its definition) and not what it does. A function does nothing. The successor function doesn’t add 1 to its argument. You can add 1 to an integer to calculate its successor, but you aren’t a function. The function

- successor(x)

*x*. It is only equivalent to x + 1, which simply means that each time you encounter the expression successor(x), you can replace it with (x + 1). Note the parentheses that are used to isolate the expression. They aren’t needed when the expression is used alone, but they might be necessary on some occasions.

**Inverse functions**

**A function may or may not have an inverse function. If f(x) is a function from A to B**(A being the domain and B the codomain),

**the inverse function is noted as f-1(x) and has B as its domain and A as its codomain. If you represent the type of the function as A –> B, the inverse function (if it exists) has the type B –> A.**

The inverse of a function is a function if it fulfills the same requirement as any function: having one and only one target value for each source value. As a result, the inverse of successor(x), a relation that you’ll call predecessor(x) (although you could just as well call it xyz), isn’t a function in N (the set of positive integers including 0) because 0 has no predecessor in N. Conversely, if successor(x) is considered with the set of signed integers (positive and negative, noted as Z), the inverse of successor is a function. Some other simple functions have no inverse. For example, the function

- f(x) = (2 * x)

**Partial functions**

A relation that isn’t defined for all elements of the domain but that fulfills the rest of the requirement (no element of the domain can have a relationship with more than one element of the codomain) is often called a

**partial function**. The relation predecessor(x) is a partial function on

*N*(the set of positive integers plus 0), but it’s a total function on N*, which is the set of positive integers without 0, and its codomain is N.

Partial functions are important in programming because many bugs are the result of using a partial function as if it were a total one. For example, the relation f(x) = 1/x is a partial function from N to Q (the rational numbers) because it isn’t defined for 0. It’s a total function from N* to Q, but it’s also a total function from N to (Q plus error).

**By adding an element to the codomain**(the error condition),

**you can transform the partial function into a total one**. But to do this, the function needs a way to return an error. Can you see an analogy with computer programs? You’ll see that turning partial functions into total ones is an important part of functional programming.

**Function composition**

Functions are building blocks that can be composed to build other functions. The composition of functions

*f*and

*g*is noted as f ˚ g, which reads as

**. If f(x) = x + 2 and g(x) = x * 2, then**

*f*round*g*- f ˚ g (x) = f(g(x)) = f(x * 2) = (x * 2) + 2

**two notations f ˚ g (x) and f(g(x)) are equivalent**. But writing a composition as f(g(x)) implies using x as a placeholder for the argument. Using the f ˚ g notation, you can express a function composition without using this placeholder.

If you apply this function to 5, you’ll get the following:

- f ˚ g (5) = f(g(5)) = f(5 * 2) = 10 + 2 = 12

**f ˚ g is generally different from g ˚ f, although they may sometimes be equivalent**. For example:

- g ˚ f (5) = g(f(5)) = g(5 + 2) = 7 * 2 = 14

*g*, and then

*f*. Standard Java 8 functions define the compose() method and the andThen() method to represent both cases (which, by the way, isn’t necessary because f.andThen(g) is the same as g.compose(f), or g ˚ f).

**Functions of several arguments**

So far, we’ve talked only about functions of one argument. What about functions of several arguments? Simply said, there’s no such thing as a function of several arguments. Remember the definition?

**A function is a relation between a source set and a target set. It isn’t a relation between two or more source sets and a target set. A function can’t have several arguments.**

**But the product of two sets is itself a set, so a function from such a product of sets into a set may appear to be a function of several arguments.**Let’s consider the following function:

- f(x, y) = x + y

Tuples are noted between parentheses, so (3, 5) is a tuple and an element of N x N. The function

*f*can be applied to this tuple:

- f((3, 5)) = 3 + 5 = 8

- f(3, 5) = 3 + 5 = 8

**it’s still a function of one tuple, and not a function of two arguments.**

**Function currying**

Functions of tuples can be thought of differently. The function f(3, 5) might be considered as a function from N to a set of functions of N. So the previous example could be rewritten as

- f(x)(y) = g(y)

- g(y) = x + y

- f(x) = g

*g*. Applying this

*g*function to y gives the following:

- g(y) = x + y

**When applying**If you apply this to (3, 5), you get the following:

*g*, x is no longer a variable. It doesn’t depend on the argument or on anything else. It’s a constant.- f(3)(5) = g(5) = 3 + 5 = 8

*f*is a set of functions instead of a set of numbers. The result of applying

*f*to an integer is a function. The result of applying this function to an integer is an integer.

**f(x)(y) is the curried form of the function f(x, y)**. Applying this transformation to a function of a tuple (which you can call a function of several arguments if you prefer) is called

**currying**, after the mathematician Haskell Curry (although he wasn’t the inventor of this transformation).

**Partially applied functions**

The curried form of the addition function may not seem natural, and you might wonder if it corresponds to something in the real world. After all,

**with the curried version, you’re considering both arguments separately. One of the arguments is considered first, and applying the function to it gives you a new function.**Is this new function useful by itself, or is it simply a step in the global calculation?

In the case of an addition, it doesn’t seem useful. And by the way, you could start with either of the two arguments and it would make no difference. The intermediate function would be different, but not the end result. Now consider a new function of a pair of values:

- f(rate, price) = price / 100 * (100 + rate)

- g(price, rate) = price / 100 * (100 + rate)

- f(rate)(price)
- g(price)(rate)

*f*and

*g*are functions. But what are f(rate) and g(price)? Yes, for sure, they’re the results of applying

*f*to rate and

*g*to price. But what are the types of these results?

**f(rate) is a function of a price to a price**. If rate = 9, this function applies a tax of 9% to a price, giving a new price. You could call the resulting function apply9-percentTax(price), and it would probably be a useful tool because the tax rate doesn’t change often.

On the other hand,

**g(price) is a function of a rate to a price**. If the price is $100, it gives a new function applying a price of $100 to a variable tax. What could you call this function? If you can’t think of a meaningful name, that usually means that it’s useless, though this depends on the problem you have to solve.

**Functions like f(rate) and g(price) are sometimes called partially applied functions**, in reference to the forms f(rate, price) and g(price, rate). Partially applying functions can have huge consequences regarding argument evaluation. We’ll come back to this subject in a later section.

If you have trouble understanding the concept of currying, imagine you’re traveling in a foreign country, using a handheld calculator (or your smartphone) to convert from one currency to another. Would you prefer having to type the conversion rate each time you want to compute a price, or would you rather put the conversion rate in memory? Which solution would be less error prone?

**Functions have no effects**

Remember that pure functions only return a value and do nothing else. They don’t mutate any element of the outside world (with outside being relative to the function itself), they don’t mutate their arguments, and they don’t explode (or throw an exception, or anything else) if an error occurs. They can return an exception or anything else, such as an error message. But they must return it, not throw it, nor log it, nor print it.

**Functions in Java**

In

**chapter 1**, you used what I called functions but were in fact methods.

**Methods are a way to represent**(to a certain extent)

**functions in traditional Java**.

**Functional methods**

A method can be functional if it respects the

**requirements of a pure function**:

Let’s look at an example.

**- Listing 2.1. Functional methods**

- public class FunctionalMethods {
- public int percent1 = 5;
- private int percent2 = 9;
- public final int percent3 = 13;
- public int add(int a, int b) {
- return a + b;
- }
- public setPercent2(int value) {
- percent2 = value;
- }
- public int mult(int a, Integer b) {
- a = 5;
- b = 2;
- return a * b;
- }
- public int div(int a, int b) {
- return a / b;
- }
- public int applyTax1(int a) {
- return a / 100 * (100 + percent1);
- }
- public int applyTax2(int a) {
- return a / 100 * (100 + percent2);
- }
- public int applyTax3(int a) {
- return a / 100 * (100 + percent3);
- }
- public List
append( int i, Listlist) { - list.add(i);
- return list;
- }
- }

- public int add(int a, int b) {
- return a + b;
- }

**Exactness**

The term exact doesn’t mean anything by itself. It generally means that it fits what is expected, so to say whether the result of a function implementation is exact, you must know the intention of the implementer. Usually you’ll have nothing but the function name to determine the intention, which can be a source of misunderstanding. Consider the second method:

- public int mult(int a, Integer b) {
- a = 5;
- b = 2;
- return a * b;
- }

Now consider the div:

- public int div(int a, int b) {
- return a / b;
- }

- public int percent1 = 5;
- public int applyTax1(int a) {
- return a / 100 * (100 + percent1);
- }

*percent1*, which is public and can be modified between two function calls. As a consequence, two function calls with the same argument could return different values.

*percent1*may be considered an

**implicit parameter**, but this parameter isn’t evaluated at the same time as the method argument. This isn’t a problem if you use the

*percent1*value only once inside the method, but if you read it twice, it could change between the two read operations.

**If you need to use the value twice, you must read it once and keep it in a local variable**. This means the method applyTax1 is a pure function of the tuple (a, percent1), but it’s not a pure function of a. Compare that with the applyTax2 method:

- private int percent2 = 9;
- public int applyTax2(int a) {
- return a / 100 * (100 + percent2);
- }

*percent2*property is private. But it’s mutable, and it’s mutated by the setPercent2 method. Because

*percent2*is accessed only once, applyTax2 can be considered a pure function of the tuple (a, percent2). But if considered as a function of a, it’s not a pure function. Now consider the sixth method:

- public final int percent3 = 13;
- public int applyTax3(int a) {
- return a / 100 * (100 + percent3);
- }

*percent3*final property, which can’t be mutated. You might think that applyTax3 isn’t a pure function because the result doesn’t depend only on the method’s arguments (the result of a pure function must depend only on its arguments). But no contradiction exists here if you consider

*percent3*as a supplemental argument. In fact, the class itself may be considered a supplemental implicit argument, because all its properties are accessible from inside the method.

This is an important notion. All instance methods can be replaced with static methods by adding an argument of the type of the enclosing class. So the applyTax3 method may be rewritten as

- public static int applyTax3(FunctionalMethods x, int a) {
- return a / 100 * 100 + x.percent3;
- }

**FunctionalMethods**instance is available. Here, applyTax3 is a pure function of the tuple (this, a). And finally, our last method:

- public List
append( int i, Listlist) { - list.add(i);
- return list;
- }

**Object notation vs. functional notation**

You’ve seen that instance methods accessing class properties may be considered as having the enclosing class instance as an implicit parameter. Methods that don’t access the enclosing class instance may be safely made static. Methods accessing the enclosing instance may also be made static if their implicit parameter (the enclosing instance) is made explicit. Consider the Payment class from chapter 1:

- public class Payment {
- public final CreditCard cc;
- public final int amount;
- public Payment(CreditCard cc, int amount) {
- this.cc = cc;
- this.amount = amount;
- }
- public Payment combine(Payment other) {
- if (cc.equals(other.cc)) {
- return new Payment(cc, amount + other.amount);
- } else {
- throw new IllegalStateException(
- "Can't combine payments to different cards");
- }
- }
- }

*cc*and

*amount*fields. As a result, it can’t be made static. This method has the enclosing class as an implicit parameter.

**You could make this parameter explicit, which would allow you to make the method static:**

- public class Payment {
- public final CreditCard cc;
- public final int amount;
- public Payment(CreditCard cc, int amount) {
- this.cc = cc;
- this.amount = amount;
- }
- public static Payment combine(Payment payment1, Payment payment2) {
- if (payment1.cc.equals(payment2.cc)) {
- return new Payment(payment1.cc, payment1.amount + payment2.amount);
- } else {
- throw new IllegalStateException(
- "Can't combine payments to different cards");
- }
- }
- }

- Payment newPayment = combine(this, otherPayment);

- Payment newPayment = Payment.combine(payment1, payment2);

- public Payment combine(Payment payment) {
- if (this.cc.equals(payment.cc)) {
- return new Payment(this.cc, this.amount + payment.amount);
- } else {
- throw new IllegalStateException(
- "Can't combine payments to different cards");
- }
- }

- Payment newPayment = p0.combine(p1).combine(p2).combine(p3);

- Payment newPayment = combine(combine(combine(p0, p1), p2), p3);

**Java functional interfaces and anonymous classes**

**Methods can be made functional, but they’re missing something that keeps them from being able to represent functions in functional programming: they can’t be manipulated besides being applied to arguments. You can’t pass a method as an argument to another method.**The consequence is that you can’t compose methods without applying them. You can compose method applications, but not the methods themselves. A Java method belongs to the class where it’s defined, and it stays there.

You can compose methods by calling them from other methods, but this must be done while writing the program. If you want different compositions depending on particular conditions, you have to lay out these compositions at writing time. You can’t write a program in such a way that the program itself will change during execution. Or can you?

Yes, you can! Sometimes you register handlers at runtime to handle specific cases. You can add handlers to handler collections, or remove them, or change the order in which they’ll be used. How can you do this? By using classes containing the methods you want to manipulate. In a GUI, you often use listeners to handle specific events such as moving the mouse, resizing a window, or typing text. These listeners are generally created as anonymous classes implementing a specific interface. You can use the same principle to create functions. Let’s say you want to create a method to triple an integer value. First, you have to define an interface with a single method:

- public interface Function {
- int apply(int arg);
- }

- Function triple = new Function() {
- @Override
- public int apply(int arg) {
- return arg * 3;
- }
- };

- System.out.println(triple.apply(2));

- Function square = new Function() {
- @Override
- public int apply(int arg) {
- return arg * arg;
- }
- };

**Composing functions**

If you think about functions as methods, composing them seems simple:

- System.out.println(square.apply(triple.apply(2)));

**Function composition is a binary operation on functions, just as addition is a binary operation on numbers.**So you can compose functions programmatically, using a method:

- Function compose(final Function f1, final Function f2) {
- return new Function() {
- @Override
- public int apply(int arg) {
- return f1.apply(f2.apply(arg));
- }
- };
- }
- System.out.println(compose(triple, square).apply(3));

**Polymorphic functions**

To make our function more reusable, you can change it into a polymorphic function by using parameterized types, which are implemented in Java using generics:

- public interface Function
{ - U apply(T arg);
- }

- Function
triple = new Function() { - @Override
- public Integer apply(Integer arg) {
- return arg * 3;
- }
- };
- Function
square = new Function () { - @Override
- public Integer apply(Integer arg) {
- return arg * arg;
- }
- };

- static Function
compose(Function f1, - Function
f2) { - return new Function
() { - @Override
- public Integer apply(Integer arg) {
- return f1.apply(f2.apply(arg));
- }
- };
- }

**Problem with function compositions**

Function composition is a powerful concept, but when implemented in Java, it presents a big danger. Composing a couple of functions is harmless. But think about building a list of 10,000 functions and composing them into a single one. (This could be done through a fold, an operation you’ll learn about in chapter 3.)

**In imperative programming, each function is evaluated before the result is passed as the input of the next function. But in functional programming, composing functions means building the resulting function without evaluating anything. Composing functions is powerful because functions can be composed without being evaluated**. But as a consequence, applying the composed function results in numerous embedded method calls that will eventually overflow the stack. This can be demonstrated with a simple example (using lambdas, which will be introduced in the next section):

- int fnum = 10_000; Function
g = x -> x; - Function
f = x -> x + 1; - for (int i = 0; i < fnum; i++) {
- g = Function.compose(f, g);
- };
- System.out.println(g.apply(0));

*fnum*is around 7,500. Hopefully you won’t usually compose several thousand functions, but you should be aware of this.

**Simplifying the code by using lambdas**

The second problem you have is that functions defined using anonymous classes are cumbersome to use in coding. If you’re using Java 5 to 7, you’re out of luck, because there’s no other way to go. Fortunately, Java 8 introduced lambdas. Lambdas don’t change the way the Function interface is defined, but they make implementing it much simpler:

- Function
triple = x -> x * 3; - Function
square = x -> x * x;

**Lambdas aren’t just a syntax simplification. Lambdas have some consequences in terms of code compilation**.

**One of the main differences between lambdas and the traditional way of writing anonymous classes is that the types on the right side of the equals sign can be omitted.**This is possible because Java 8 comes with new capabilities regarding

**type inference**.

Prior to Java 7, type inference was possible only when chaining identifier dereferencing, such as this:

- System.out.println();

*out*, and Java is able to find it. If you were to write this without chaining, you’d have to specify the type:

- PrintStream out = System.out;
- out.println();

- List
list = new ArrayList<>();

**ArrayList**because Java is able to infer it by looking at the declaration. The same thing is possible with lambdas:

- Function
triple = x -> x * 3;

*x*is inferred by Java. But this isn’t always possible. When Java complains that it isn’t able to infer the type, you have to write it explicitly. Then you must use parentheses:

- Function
triple = (Integer x) -> x * 3;

**Specifying function types**

Although Java 8 introduced lambdas to ease function implementation, it’s missing the same kind of tool to simplify writing function types. The type of a function from an Integer to an Integer is

- Function

- x -> expression

- Integer -> Integer square = x -> x * x;

- static Function
Compose(Function f1, Function f2) { - return arg -> f1.apply(f2.apply(arg));
- }

## 沒有留言:

## 張貼留言