Closed GoogleCodeExporter closed 9 years ago
Thanks!
Also see these blog posts (and my comments on them)
http://blogs.warwick.ac.uk/chrismay/entry/writing_functional_java
http://stephan.reposita.org/archives/2007/10/17/creating-a-fluent-interface-for-
google-collections/
In short, the "FP" features of the library could definitely be made a lot
better,
although we have to make a decision about whether it's central or tangential to
what
our library is trying to offer.
Original comment by kevin...@gmail.com
on 22 Oct 2007 at 5:47
Hi Kevin,
I read your comments. But I dont liked a little of the one in url:
http://stephan.reposita.org/archives/2007/10/17/creating-a-fluent-interface-for-
google-collections/
You wrote:
"The other fix that I had in mind: make Function and Predicate into abstract
classes
which have the transform(), filter(), and other related methods right there on
them."
I think that Function and Predicate must to continue as interfaces.
However, you can to make abstract classes that implements each one them.
Thus, the API continues flexible.
Original comment by jonhnnyw...@gmail.com
on 23 Oct 2007 at 6:50
Of course there must be interfaces.
In my experience it's very rare that people wouldn't extend the abstract class.
But
I have had a case where I wanted some predicates to be enums, and I wouldn't
close
off that possibility.
The interesting question is: if usage of the abstract class proves to be 10,
20, 50
times more popular than usage of the interface, does it merit a reversal of the
usual
naming practice? That is, instead of "class AbstractPredicate" and "interface
Predicate", is there justification for "class Predicate" and (don't spew your
coffee,
please) "interface IPredicate"?
Heresy, I know, but I get paid to consider heresy :)
What I really fear is making the line
Predicate<Set<? extends Number>> containsFive = new Predicate<Set<? extends
Number>>() {
yet another eight characters longer, due to the need to instantiate
AbstractPredicate
instead.
Original comment by kevin...@gmail.com
on 23 Oct 2007 at 6:58
Hi Kevin,
While using google-collections in my project, I created FunctionChain class
that may
solve this problem. You can look at the code here:
http://docs.google.com/View?docID=d35w57w_0fc5tk2&revision=_latest
Usage example:
Iterables.any(annotations,
self(Annotation.class).function(annotation_type).select(isInstanceOf(Foo.class))
);
I tried to address 2 things: (a) keep Function as interface (b) get rid of
NPE's by
creating NullSafeFunctionChain, the idea is to let functions that declare
@Nullable
parameter in apply() to handle nulls, and skip invocations of the ones that
don't
declare @Nullable so that null just gets passed up the chain.
What do you think?
-- Yardena.
Original comment by ymeym...@gmail.com
on 4 Nov 2007 at 4:14
We have been experimenting internally with "fluent" versions of common types.
The notion here is to follow the lead of the pair:
java.util.Comparator (interface)
com.google.common.collect.Ordering (abstract class)
The latter implements the former, has a from() method taking the former, and is
in
all ways the same thing as the former except having more awesome functionality
built-in.
This seems like a pattern that, while not totally 100% awesome, is worth
following
because we don't have any better idea how to do this.
So what we're playing with:
Comparator --> Ordering
Iterable --> FluentIterable (??)
Predicate --> Matcher (??)
Function --> FluentFunction (??)
For example, FluentIterable looks like this:
abstract class FluentIterable<T> implements Iterable<T> {
FluentIterable<T> unmodifiable()
FluentIterable<T> filter(Predicate<? super T>)
<S> FluentIterable<S> transformWith(Function<? super T, S>)
FluentIterable<T> append(Iterable<? extends T>)
FluentIterable<List<T>> partition(int)
FluentIterable<T> skip(int)
FluentIterable<T> limit(int)
FluentIterable<T> cycle()
int size()
boolean isEmpty()
boolean contains(@Nullable Object)
boolean elementsEqual(Iterable<?>)
T[] toArray(Class<T>)
String toString()
ImmutableList<T> toList()
T getOnlyElement()
T getLast()
int frequency(@Nullable Object)
T firstMatching(Predicate<? super T>)
boolean anyMatches(Predicate<? super T>)
boolean allMatch(Predicate<? super T>)
}
Any input?
Original comment by kevin...@gmail.com
on 17 Mar 2009 at 4:49
Years ago I had experimented with returning "ExtendedIterable" (and other such
types)
from methods, which offered filtering and other utilities, but I came to
dislike
these and prefer the simplicity of google collections, in the form of not
introducing
new types for just syntactical "niceties", like calling "x.m(y)" instead of
"m(x, y)"
(modulo polymorphism, which you don't need, it's merely a syntactical twist).
Would
you feel comfortable with having FluentCollection, FluentSet, FluentMap,
FluentMultimap etc? I doubt. Or for example:
What if a method wants to return a _Set_ (to denote element uniqueness)
that is also "fluent"?
- Return a FluentIterable, which is not a Set?
- Return a Set, which is not FluentIterable?
- Return a FluentSet?
In the case of Ordering, I see comparator as a SPI and Ordering as its
respective
API. "You implement just this method(s), and you get for free all these". It
looks
good, I think static methods would be fine too. I understand you like the
ability to
hit "[dot]" and get the pop-up of your IDE, but hitting "[dot]" after typing
"Ordering" would do the job as well. Also note that the Ordering methods are
not also
offered as statics, so they offer something genuine, while the types you
describe
would not.
So, I would hope you continue to prefer simplicity over slight syntactical
gains, as
you always have done in google collections.
I also want to draw some attention to the fact that this conversation wouldn't
need
to ever happen if the initial collection types were defined as abstract
classes, and
not interfaces. All convenience methods could be then defined in them. But
then,
existing classes with existing superclasses (other than Object) wouldn't be
able to
implement these collection types. This restriction doesn't exist for example in
scala, where traits (interfaces that can have code) can be freely mixed in
classes
without affecting their class hierarchy, i.e. very easy reuse. So there is no
reason
not to define convenience methods directly in the collection types, and this is
how
is done. But since we talk about java, lets not try to fix the absense of
certain
language features by library design - this would encourage everyone to follow
suit.
Original comment by jim.andreou
on 17 Mar 2009 at 6:14
You certainly are right that I'd hate to see this proliferate to Set and Map
and all
that.
If Ordering/Comparator is a little different from the rest (API/SPI), then
Function
and Predicate fall into this category as well. They're very much the same
flavor of
objects. (The point about how the functionality is not also offered with
statics --
well, it *was*, we just undid all that is all.)
So it's really FluentIterable that is most controversial here. Well -- I love
FluentIterable. I think it makes code a lot more readable and library features
more
discoverable. But I can't predict whether it will ever become part of this
library or
not. Your input has been useful, as will be the input of others who might wish
to
give it here.
Original comment by kevin...@gmail.com
on 17 Mar 2009 at 9:40
I second the vote for having interfaces that define all these new fluent methods.
Whatever blasphmous name they might have, they are needed. Indeed, I'm currently
missing an interface for the Ordering.
So it goes like:
Iterable -> i Whatever -> abs Whatever
Comparator -> i Ordering -> abs Ordering
i Function -> abs Function
i Predicate -> abs Predicate
Then, if you're introducing upgraded interface for Iterables/Comparators and
Functions/Predicates with fluent methods, you're going to use them in APIs (and
not
only g-col ones, you're going to pass them around in your software). That way,
even
if you almost always use abstract classes that implement all that fluency as a
base
for your anonymous classes, the number of said anon classes would be on even,
if not
dwarfed by interface API usages.
From that point I'm no longer sure which names should be shorter. What I'm not
eager to see is AbcInterface or AbstractAbc. BaseAbc sounds better. IAbc even
more.
I'd really like to have +1letter naming for abstract classes, but can't choose
a letter.
What about naming upgraded Iterable a Sequence?
Predicate is a cool name, it goes better with Function and it doesn't clash with
java.util.regex.Matcher, which is much more probable to meet in the same
context,
than all non-g-col Predicates I could find.
Hopefully, I was able to convey my thoughts :)
Original comment by earwin@gmail.com
on 17 Mar 2009 at 10:22
I still don't see the advantage of an interface for Ordering. Can you try
again to
explain it?
Whatever the "better" Iterable is, I'm convinced it must include "Iterable".
Picking
another term out of the air like "Sequence" is just going to mislead people;
that may
mean something else to them. An Iterable is exactly what this is, just with
more stuff.
By this rationale the name Ordering was a mistake, and maybe it was, but it's
one we
already made and we'll live with it. And by this rationale, the name "Matcher"
is
wrong for the upgraded Predicate, and I think it is indeed wrong, for these
reasons
as well as conflict with all the dozens of other things called Matcher in the
world.
So I think we'll have to fix that, but to what?
Original comment by kevin...@gmail.com
on 17 Mar 2009 at 11:00
Similar to your case - an ability to use Ordering enums.
Other case is when you have your own working hierarchy of classes and want them
to be
FluentWhatevers. This case is shaky, it's more applicable to
iterables/functions/predicates than to ordering and you can always have a method
returning delegating FluentWhatever.
It's just a joke, but what about taking your words literally and using
BetterIterable?
Original comment by earwin@gmail.com
on 19 Mar 2009 at 7:18
But an Ordering enum would be such an incredible burden to implement! Don't
bother;
have an enum from which you can *get* an ordering.
As well, remember than any interface we release is something we can never, ever
add a
method to or otherwise change in basically any way.
"BetterIterable"? Believe me, we considered it. We tried *everything*.
NiceIterable, RichIterable, SuperIterable, Iterabler, Iterablest, IterablePlus,
IterablePlusPlus, DeluxeIterable, Iterable2, MintyFreshIterable,
OrganicFreeRangeIterable, IterableThatIsTehHotness, PhatIterable,
BarackObamaWouldUseThisIterable, Bob . . .
Original comment by kevin...@gmail.com
on 19 Mar 2009 at 7:40
Maybe you should put less weight to API discoverability, and trust your users
to know
it, and read the documentation (assuming that at some point in time some kind
of
tutorial will be written, in the spirit of java collections). If this thing is
going
to be used as widely as java collections, which I believe that at some point it
will,
it will be common ground for java developers to know its basics, as much you
take for
granted that java developers know the existence of java.util.Collections
utilities.
(A question, in order to understand the precise dilemma: if you introduce
FluentIterable, you would remove the similar methods from Iterables? Or keep
them
redundantly?)
Original comment by jim.andreou
on 19 Mar 2009 at 8:48
It's too late to have any other choice but to keep them redundantly.
Original comment by kevin...@gmail.com
on 19 Mar 2009 at 8:51
Original comment by kevin...@gmail.com
on 17 Sep 2009 at 6:02
Take a look at ParallelArray: "The ParallelArray library builds on top of
fork-join
and provides a functional style API for mapping, filtering, reducing, etc over
an
array of Java objects. Without closure support, the API is not particularly
pretty,
but I think it’s eminently useful. The decision was made not to standardize
it in the
JDK yet but you can still download it from the JSR 166 site directly."
http://gee.cs.oswego.edu/dl/jsr166/dist/extra166ydocs/extra166y/ParallelArray.ht
ml
Original comment by jonhnnyw...@gmail.com
on 16 Nov 2009 at 12:59
This issue has been moved to the Guava project (keeping the same id number).
Simply replace 'google-collections' with 'guava-libraries' in your address
bar and it should take you there.
Original comment by kevinb@google.com
on 5 Jan 2010 at 11:09
Original issue reported on code.google.com by
jonhnnyw...@gmail.com
on 22 Oct 2007 at 5:12Attachments: