Java Reference
In-Depth Information
calculate eagerly) but that can be created on demand. This would be a lazy tree as opposed to a
lazy list. We concentrated on lazy lists because they provide a link back to another Java 8 feature,
streams, and we could then discuss the pros and cons of streams compared to lazy lists.
There remains the question of performance. It's easy to assume that doing things lazily will be
better than doing things eagerly—surely it's better to calculate only the values and data
structures needed by a program on demand than to create all those values (and perhaps some
more) as done under traditional execution. Unfortunately, the real world isn't so simple. The
overhead of doing things lazily (for example, the additional Suppliers between each item in your
LazyList) outweighs the notional benefit unless you explore, say, less than 10% of the data
structure. Finally, there's a subtle way in which your LazyList values aren't truly lazy. If you
traverse a LazyList value such as from(2), perhaps up to the 10th item, then it also creates all the
nodes twice, thus creating 20 nodes rather than 10. This is hardly lazy. The issue is that the
Supplier in tail is repeatedly called on each on-demand exploration of the Lazy-List; you can fix
this by arranging that the Supplier in tail is called only on the first on-demand exploration—and
its resulting value is cached—in effect solidifying the list at that point. This can be achieved by
adding a private Optional<LazyList<T>> alreadyComputed field to your definition of LazyList
and arranging for the method tail to consult and update it appropriately. The pure functional
language Haskell arranges that all its data structures are properly lazy in this latter sense. Read
one of the many articles on Haskell if you're interested.
Our guideline is to remember that lazy data structures can be a useful weapon in your
programming armory. Use them when they make an application easier to program. Rewrite
them in more traditional style only if they cause unacceptable inefficiency.
Now let's turn to another feature of almost all functional programming languages but one that's
lacking from Java: pattern matching.
14.4. Pattern matching
There's one other important aspect to what's generally regarded as functional programming,
and that's (structural) pattern matching (not to be confused with pattern matching and regex).
Recall that chapter 1 ended by observing that mathematics can write definitions such as
f(0) = 1
f(n) = n*f(n-1) otherwise
whereas in Java, you have to write an if-then-else or a switch statement. As data types become
more complex, the amount of code (and clutter) needed to process them increases. Using
pattern matching can reduce this clutter.
 
Search WWH ::




Custom Search