I know one of the goals of pure functional programming is to eliminate mutability, and therefore to preclude side-effects. But let's face it, Java is not a functional language even with all of the functional-programming libraries that exist. In fact it seems that some of the FP-libraries know and expect this. For instance in Functional Java, there is the Effect class. In the Jedi FP library, there is the Command interface. This allows you to -- among other things -- apply a command pattern with type-safety to elements of an Iterable without the nasty for-loop boilerplate.
Command makeCall = new Command {
public void execute(PhoneNumber p) { p.call(); }
}
List phoneList = ...
FunctionalPrimitives.forEach( phoneList, makeCall );
So the question is, is there anything like that in Guava?
EDITED AFTER ANSWER ACCEPTED FOR CLARIFICATION
I am developing a framework that helps with the "vertical problem" inherent in most Java FP-libraries, under a certain set of circumstances. So I would not actually make the code example as shown above: i.e., explicitly declare a new class implementation of Command with all of its vertical-noise icky-ness, simply for the purpose of immediately applying it right after the declaration.
I was thinking more along the lines of the actual command pattern, where there may be several possible commands declared elsewhere, and only one of them gets passed into the code which wants to apply it iteratively. Furthermore, the goal of my framework is to make it more idiomatic to create functional-interface objects (functions, predicates, commands, other simple lambdas) without simply moving the vertical problem elsewhere. I have long realized this is not within the scope of Guava. But as Command-like interface are available in other FP libraries, I just wanted to know if an analog existed in Guava.
A more complete code example, using my framework, might be something like this:
class Stuff {
private final Stuff CALLS_TO = callsTo(Stuff.class); // a proxy
public static final Command CMD1 = commandFor(CALLS_TO.someMethod1());
public static final Command CMD2 = commandFor(CALLS_TO.someMethod2());
// methods exist for use elsewhere, but are conveniently also wrapped as commands
public void someMethod1() {...}
public void someMethod2() {...}
}
class Activity {
public void handleIt(List stuffs, Command doCmd) {
doSomeThings();
...
forEach(stuffs, doCmd);
...
doOtherThings();
}
}
解决方案
Nope!
Kevin Bourrillion, the Guava project lead, has said on Guava's functional features:
“The syntax sucks. At the same time, this stuff is now, has always been and will always be nothing but a stopgap measure until the right language change can come along, at which time we can finally really decide on the optimal syntax and have functional-style programming start actually making lives better in Java for once. So I’m undecided how much effort to put into the Function/Predicate stuff; it’s in the library more because it sort of had to be, not so much because we think it’s a crown jewel.”
We will probably change our strategy significantly when Java 8 comes along, but that won't be for a while yet.
Also, we haven't found many use cases for which we think the Command interface you describe would be the best solution. For example, we think that your above code would be much better written as
for(PhoneNumber phone : phoneList) {
phone.call();
}
the old-fashioned way. We could potentially be convinced of the merit of Command, but I think the "for-each" use case is almost always better done the old-fashioned way.