Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FluentPredicate #334

Closed
gissuebot opened this issue Oct 31, 2014 · 22 comments
Closed

FluentPredicate #334

gissuebot opened this issue Oct 31, 2014 · 22 comments

Comments

@gissuebot
Copy link

Original issue created by blank101 on 2010-02-26 at 11:00 PM


I find the following very annoying:

Predicates.and(Predicates.not(Predicates.in(someCollection)),Predicates.not
Null())

...etc.

I wrote a (very bare) wrapper implementation of Predicate (attached), which
provides for all the methods in Predicates in a functional style (ala the
similar proposal for Iterables), which allows some thing like:

ComposablePredicate.in(someCollection).not().and(Predicates.notNull())

which I think is more clear than the example above. I don't see this in the
dead ideas or otherwise closed issues, so I thought I'd suggest it.

The one implementation decision I'm not sure about is an immutable vs
mutable delegate, but I'm pretty happy with the immutable version.

N.B.: this composition problem also applies to functions: e.g.,
Functions.blah(Functions.blah(Functions.blah( ... ) becomes rapidly
unreadable for any substantive number of functions.

@gissuebot
Copy link
Author

Original comment posted by kevinb@google.com on 2010-02-27 at 12:48 AM


We have great "fluent" versions of Predicate, Function and Iterable, and I hope we can
release them soon. The only real problem is that these classes are THE hardest things
to name EVER.

Right now the best I have come up with is FluentPredicate, FluentFunction and
FluentIterable. :(

@gissuebot
Copy link
Author

Original comment posted by blank101 on 2010-02-27 at 05:41 AM


Fluid_, perhaps - one character shorter, aye? Or perhaps Flow_. Maybe even Flo*, if
it doesn't conjure up to much an advertising theme.

@gissuebot
Copy link
Author

Original comment posted by david.henderson on 2010-03-09 at 10:31 PM


The term "Chainable" is used in some contexts.

@gissuebot
Copy link
Author

Original comment posted by blank101 on 2010-03-09 at 11:27 PM


I know IDEs, auto-completion, blah-blah-blah...but "Chainable" is really long.

The "Fluent" moniker seems to have some traction, and the original metaphor for that
moniker seems to explicitly include the notion of "Flow"; I'm not particularly fond of
"Fluent" (too ambiguous, too long), hence would prefer "Flow" as the prefix (and that's
how I've named my parallel Collections framework), but it would be a reasonable name.

@gissuebot
Copy link
Author

Original comment posted by cgdecker on 2010-03-09 at 11:55 PM


"Flow" is a noun or a verb, not an adjective which can describe something.
"FlowPredicate" does not read naturally (to me, anyway) and saving 2 characters doesn't
seem worth using a name that neither reads well nor describes the class as well as
Fluent. That said, I think if Kevin felt this general category of names was what he
really wanted to use for these classes he'd just have used Fluent and been done with
it. I imagine he's looking for something more on the lines of Ordering.

@gissuebot
Copy link
Author

Original comment posted by blank101 on 2010-03-10 at 01:22 AM


You mean, something more like:

Function -> Composite
Predicate -> Filter

?

I still think I consistent prefix would be preferable. The basic behavior of all these
things (functions, predicates, iterables, iterators, etc) remains largely consistent with
their "parent" objects, but each has the same sort of sequentially callable
transformation methods appended.

@gissuebot
Copy link
Author

Original comment posted by daniel.yokomizo on 2010-03-10 at 07:58 AM


This fluency support could be extended to more than predicates/functions/iterables.
In my Collections Framework I use (using the equivalent guava names):

interface Filterable<E> {
    Filterable<E> filter(Predicate<? super E> p);
}
interface Transformable<E> {
    <F>Transformable<F> transform(Function<? super E,? extends F> f);
}
interface Composable<E> {
    <D>Composable<D> compose(Function<? super D,? extends E> f);
}
interface FluentFunction<D,E> extends Transformable<E>, Composable<D>, Function<D,E>
{
    // equivalent to Functions.compose
    <F>FluentFunction<D,F> transform(Function<? super E,? extends F> f);
    // equivalent to Functions.compose
    <C>FluentFunction<C,E> compose(Function<? super C,? extends D> f);
}
interface FluentPredicate<E> extends Filterable<E>, Composable<E>, Predicate<D,E> {
    // equivalent to Predicates.and
    FluentPredicate<E> filter(Predicate<? super E> p);
    // equivalent to Predicates.compose
    <D>FluentPredicate<D> compose(Function<? super D,? extends E> f);
    FluentPredicate<E> and(Predicate<? super E> p);
    FluentPredicate<E> or(Predicate<? super E> p);
    FluentPredicate<E> not();
}
interface FluentIterable<E> extends Transformable<E>, Filterable<E>, Iterable<E> {
    // equivalent to Iterables.filter
    FluentIterable<E> filter(Predicate<E> p);
    // equivalent to Iterables.transform
    <F>FluentIterable<F> transform(Function<? super E,? extends F> f);
}
interface FluentIterator<E> extends Transformable<E>, Filterable<E>, Iterator<E> {
    // equivalent to Iterables.filter
    FluentIterator<E> filter(Predicate<E> p);
    // equivalent to Iterables.transform
    <F>FluentIterator<F> transform(Function<? super E,? extends F> f);
}
interface FluentCollection<E> extends Collection<E>, FluentIterable<E> {
    // equivalent to Collections2.filter
    FluentCollection<E> filter(Predicate<E> p);
    // equivalent to Collections2.transform
    <F>FluentCollection<F> transform(Function<? super E,? extends F> f);
}
// and so on, giving FluentMap, FluentList, FluentQueue, FluentSet, FluentSortedMap,
FluentSortedSet
// we can add FluentFuture, FluentThreadLocal, etc. as we would like

class Fluency {
   public static <E> FluentIterable from(Iterable<E> iterable);
   public static <E,F> FluentFunction from(Function<? super E,? extends F> function);
// and so on
}

@gissuebot
Copy link
Author

Original comment posted by blank101 on 2010-03-10 at 01:27 PM


That is very similar to what I do; I do put the additional interface requirement for
FluentIterable that the iterator() method return a FluentIterator. Also, for the various
collections, I included fluent versions of the mutators (fluentAdd, fluentRemove, etc).

Also my base interfaces (the Filterable, Composable, Transformable equivalents) I
covered more of the functionality in the Predicates, Functions, Iterables, Iterators
static helper classes.

What are the specifics of your Fluent map? It's not as obvious to me what's being
filtered/transformed/etc with both keys and values.

@gissuebot
Copy link
Author

Original comment posted by daniel.yokomizo on 2010-03-10 at 10:09 PM


As you said I also put the additional constraints of FluentIterable returning a
FluentIterator on iterator(). FluentMap is similar, it returns a FluentSet on keySet()
and entrySet() and a FluentCollection on values(). Also it implements
Filterable<Map.Entry<K,V>> but not Transformable (it's not a pressing need for me).

@gissuebot
Copy link
Author

Original comment posted by finnw1 on 2010-04-23 at 01:46 PM


So will you also be renaming "Ordering" to "FluentComparator"?

@gissuebot
Copy link
Author

Original comment posted by kevinb@google.com on 2010-04-23 at 02:52 PM


That horse is out of the gate.

@gissuebot
Copy link
Author

Original comment posted by blank101 on 2010-04-23 at 04:35 PM


Indeed; any news on when the other fluent horses will be released?

@gissuebot
Copy link
Author

Original comment posted by fry@google.com on 2011-01-26 at 10:46 PM


(No comment entered for this change.)


Status: Accepted
Labels: Type-Enhancement

@gissuebot
Copy link
Author

Original comment posted by kevinb@google.com on 2011-07-13 at 06:18 PM


(No comment entered for this change.)


Status: Triaged

@gissuebot
Copy link
Author

Original comment posted by fry@google.com on 2011-12-10 at 03:45 PM


(No comment entered for this change.)


Labels: Package-Base

@gissuebot
Copy link
Author

Original comment posted by wasserman.louis on 2012-02-16 at 06:48 PM


(No comment entered for this change.)

@gissuebot
Copy link
Author

Original comment posted by fry@google.com on 2012-02-16 at 07:17 PM


(No comment entered for this change.)


Status: Acknowledged

@gissuebot
Copy link
Author

gissuebot commented Oct 31, 2014

Original comment posted by em...@soldal.org on 2012-05-08 at 01:19 PM


These are the slowest horses ever!

@gissuebot
Copy link
Author

Original comment posted by kevinb@google.com on 2012-05-30 at 07:43 PM


(No comment entered for this change.)


Labels: -Type-Enhancement, Type-Addition

@gissuebot
Copy link
Author

Original comment posted by kevinb@google.com on 2012-06-22 at 06:16 PM


(No comment entered for this change.)


Status: Research

@sarod
Copy link

sarod commented Jun 18, 2015

Any Progress on FluentPredicates and FluentFunctions?

@jbduncan
Copy link
Contributor

I think this issue is now resolved with the introduction of the java.util.function.{Predicate, Function, ...} functional interfaces in Java 8, and with com.google.common.base.{Predicate, Function, ...} now extending those interfaces.

For example, Predicate has the "fluent" methods and, or and negate, which I think fulfill the OP's original request, as one can now write the following quite easily:

com.google.common.base.Predicates.in(collection).negate().and(Objects::nonNull);

Therefore I believe that this issue can and should be closed now. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants