Anything in Guava similar to Functional Java's Effect?
Asked Answered
C

1

6

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<PhoneNumber> makeCall = new Command<PhoneNumber> {
    public void execute(PhoneNumber p) { p.call(); }
}
List<PhoneNumber> 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<Stuff> CMD1 = commandFor(CALLS_TO.someMethod1());
    public static final Command<Stuff> 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<Stuff> stuffs, Command<Stuff> doCmd) {
        doSomeThings();
        ...
        forEach(stuffs, doCmd);
        ...
        doOtherThings();
    }
}
Caren answered 1/3, 2012 at 23:41 Comment(0)
M
10

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.

Myranda answered 2/3, 2012 at 0:4 Comment(8)
Why is the "old-fashioned" way better for commands, but not better for filters and transformations? Also, I know the functional features are seen as stop gap until Java 8, but you have to realize that Java 8 is some time off, and adoption of it will not be immediate. There are still projects stuck Java 5 (luckily, not mine).Caren
If you read the user guide, you'll see that we think the old-fashioned way is better for filters and transformations most of the time. Not all of the time -- which is why we provide those features -- but most of the time.Myranda
In addition, the original post's code appears to be an example of the very thing that makes the Guava team weep.Wickner
I have read that section ample times, and I agree with it in principle but think that it is way too amplified. In my tastes, it is much more readable my one-line way than what you showed, not just because it's one line but because it actually reads more naturally. The example given in the Caveats section of the user guide is clearly one where you are combining a Function and Predicate. Also I make an FOSS library that helps produce Functions and Predicates that wrap existing getters in a single line. So there is definitely a net code savings too.Caren
Yeah @Justin, I have always loved that comment, but clearly my OP looks nothing like the example that makes them weep in terms of complexity. And in my above comment, you will see that I have a proposed solution for the "vertical problem"Caren
a) Guava is, conceptually speaking, aimed at users with the raw JDK and nothing else. b) I wrote the user guide section we're discussing, and yes, your example, too, makes me weep. c) If you really want to have this discussion, we can continue it on guava-discuss, but SO really isn't the place for it. I've explained that there isn't any such thing in Guava and why.Myranda
@KevinWelker: There's a huge difference between this and filter/transform. Filter/transform do something that cannot be done using a loop: they produce a view in constant time. A for-each like in your example is inherently replaceable with a loop.Brassica
@Louis, thanks, yes you did actually answer the OP question clearly. I just was getting caught up in the editorial. I'd like to say more about where I was going with this, 'cuz I can see that on its own the OP code example could still look ugly w/o context. But I will defer for now and maybe pick a conversation in guava-discuss (which I monitor closely). Thanks for answering.Caren

© 2022 - 2024 — McMap. All rights reserved.