Hello,
We've been trying Akka in my job at Alcatel-Lucent Submarine Networks. We had not problem using it from Java. We did not adopt it because we needed permanent connections for remote actors, which Akka does not provide. This results in a requirement by which it must be possible to establish a connection from both sides, which was incompatible with our use cases.
The chapter you are mentioning is not about Akka. It is about creating a (minimal) actor system in order to understand the principles.
Regarding the future of Java, it seems that Java 8 was first seen as en enthusiastic move toward functional programming. But things have changed since then, I guess due to the reaction of some users that were afraid of having to learn a new paradigm. We saw the same kind of reaction with the introduction of generics.
Lambdas were a great addition. Stream are more controversial. They lack many functional features and they are not really lazy. The main missing features for Streams (seen as lazy collections) would be a lazy (right) fold.
Regarding Optional, one should read what Brain Goetz wrote about it:
Should Java 8 getters return optional type?
The real problem is to agree about what "optional data" means. there is nothing wrong about using
null references inside a component. The problem starts when
null leaks to other components, because it does not have the same meaning. For example, an optional
String can be
null. We might also represent it with and
Optional<String>, with a cost: it is no longer a
String. But it we return a
null String from a method and someone wants to read the first character, what should be the result? Whether the programmer checks for
null before calling
charAt(0) is irrelevant. Not doing so is a bug. But
testing does not solve the problem.
Kotlin (which I see like a much better Java from this perpective) does it like this:
will return the first character if the
string is not
null and
null otherwise. But it is not the same
null. It is a
null Char, although it was formerly a
null String. This is how Kotlin makes
null to compose. Java 8 uses
Optional. But transforming an
Optional<String> into an
Optional<Char> does not solve the problem. The
word "optional" probably does not mean the same thing at both levels. When building a
Stream with a function and a seed, it makes sense for that function to return
Optional, which simply means we have reached the end. But returning
null would be ok too. From the business perspective, data is rarely truly optional. Searching for a name in a map and returning
null might mean that the name is not in the map or that it is in the map, associated to a
null value. From this perspective,
Optional might be better, but only if the map stores raw values, and not
Optionals. Otherwise, we would have the same problem. But at the business level, it might happen that the name should have been in the map, so that the absence is the result of a bug. But by composing the
Optional result with other functions that might also have returned
Optional, we have lost the reason for the absence. This is why
Optional is not very useful:
you should not make it leak out of any component. What we need is a type which carry the reason for the absence. This corresponds to the
Try type in Scala, or the
Result type I describe in the book.
There is much more to be said about
Optional, but it would be too long! But remember that there is no such thing as a "functional language". Only languages that are more functional friendly than others. Even Haskell is not functional enough for some. (Look at "Safe Haskell!"). So noone should wait for the "right language" to write functional programs. You can write functional programs in any language. It is just easier with some than with others