Java Reference
In-Depth Information
the data structures reachable from it, is not mutated. Now suppose you perform a textually
identical call in the additional assignment:
t3 = fupdate("Will", 26, t);
Now t3 will point to three more newly created nodes, containing the same data as those in t2.
The question is this: “Is fupdate referentially transparent?” Referentially transparent means
“equal arguments (the case here) imply equal results.” The problem is that t2 and t3 are
different references and therefore (t2 == t3) is false, so it looks as if you'll have to conclude that
fupdate isn't referentially transparent. But when using persistent data structures that aren't to
be modified, there's logically no difference between t2 and t3.
We can debate this point at length, but the simplest adage is that functional-style programming
generally uses equals to compare structured values rather than == (reference equality) because
data isn't modified, and under this model fupdate is referentially transparent.
14.5.3. Combinators
In functional programming it's common and natural to write a higher-order function (perhaps
written as a method) that accepts, say, two functions and produces another function somehow
combining these functions. The term combinator is generally used for this idea. Much of the
new Java 8 API is inspired by this idea; for example, thenCombine in the CompletableFuture
class. This method takes two CompletableFutures and a BiFunction to produce another
CompletableFuture.
Although a detailed discussion of combinators in functional programming is beyond the scope of
this topic, it's worth looking at a couple of special cases to give the flavor of how operations that
take and return functions are a very common and natural functional programming construct.
The following method encodes the idea of function composition :
static <A,B,C> Function<A,C> compose(Function<B,C> g, Function<A,B> f) {
return x -> g.apply(f.apply(x));
}
It takes functions f and g as arguments and returns a function whose effect is to do f first and
then g. You can then use this to define an operation, which captures internal iteration as a
combinator. Let's look at the case where you wish to take data and apply function f to it
repeatedly, say n times, as in a loop. Your operation, let's call it repeat, takes a function, f, saying
what happens in one iteration and returning a function that says what happens in n iterations. A
call such as
 
Search WWH ::




Custom Search