Re: [guava] Why not create Range.none() ?

1,030 views
Skip to first unread message

Raymond Rishty

unread,
Jan 10, 2013, 8:48:22 AM1/10/13
to Martin Steiger, guava-discuss
#1 and #4 I think would be non-controversial.
#2 I'd expect .equals(x)  to be true; Identity might be a little strong to ask for.
#3 I would disagree with--to be consistent with the contract, it should throw the Exception.


On Thu, Jan 10, 2013 at 8:43 AM, Martin Steiger <goo...@martin-steiger.de> wrote:
Hi,
I am using guava Range extensively to compute min/max pairs of lists of doubles.

List<Double> list = queryMeasurementValues(..);
Range<Double> range = computeBounds(list);

allInclusiveRange = range.span(<all-other-ranges>)

In case that the list is empty I currently return "null" which is not that great, because I need to explicitly test for "null" all the time
See also http://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained

It would be nice to have an explicit "neutral" range element that has the following properties:

Range range = Ranges.invalid/empty/neutral/none/etc..

range.contains(val) == false
range.span(range, x) == x  (this would be super helpful for me)
range.intersection(range, x) == range  instead of IllegalArgException
range.isEmpty() == true

Wouldn't that be a) possible and b) helpful ?

cheers!

--
guava-...@googlegroups.com
Project site: http://guava-libraries.googlecode.com
This group: http://groups.google.com/group/guava-discuss
 
This list is for general discussion.
To report an issue: http://code.google.com/p/guava-libraries/issues/entry
To get help: http://stackoverflow.com/questions/ask (use the tag "guava")

Kevin Bourrillion

unread,
Jan 10, 2013, 11:13:38 AM1/10/13
to Martin Steiger, guava-...@googlegroups.com
It would "be nice" in certain cases, but it breaks the basic nature of what a Range is.  A range is its boundaries.  What are the boundaries of "the empty range"?

ContiguousSet is range-like and can be empty, but that's little help to you when your element type is not discrete.  However, once we release Guava 14, you can try using RangeSet instead. A RangeSet can be empty, simply containing no Ranges.



On Thu, Jan 10, 2013 at 5:43 AM, Martin Steiger <goo...@martin-steiger.de> wrote:
Hi,
I am using guava Range extensively to compute min/max pairs of lists of doubles.

List<Double> list = queryMeasurementValues(..);
Range<Double> range = computeBounds(list);

allInclusiveRange = range.span(<all-other-ranges>)

In case that the list is empty I currently return "null" which is not that great, because I need to explicitly test for "null" all the time
See also http://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained

It would be nice to have an explicit "neutral" range element that has the following properties:

Range range = Ranges.invalid/empty/neutral/none/etc..

range.contains(val) == false
range.span(range, x) == x  (this would be super helpful for me)
range.intersection(range, x) == range  instead of IllegalArgException
range.isEmpty() == true

Wouldn't that be a) possible and b) helpful ?

cheers!

--
guava-...@googlegroups.com
Project site: http://guava-libraries.googlecode.com
This group: http://groups.google.com/group/guava-discuss
 
This list is for general discussion.
To report an issue: http://code.google.com/p/guava-libraries/issues/entry
To get help: http://stackoverflow.com/questions/ask (use the tag "guava")



--
Kevin Bourrillion | Java Librarian | Google, Inc. | kev...@google.com

Gregory Kick

unread,
Jan 10, 2013, 1:49:40 PM1/10/13
to Kevin Bourrillion, Martin Steiger, guava-discuss
To follow-up here, you currently have a few options:
1) Make an empty Range of the form [a..a) or (a..a] if that makes sense for your app.  Just be aware of the interactions with other ranges.
2) Use Optional<Range<Whatever>>.  It has a lot of nice properties over null.
3) Hold references to NavigableSet instead of Range.  In cases where the contents are more important than the boundaries, ContiguousSet is often the better choice as it also is very memory-efficient, but you can use ImmutableSortedSet.of() for an empty Set.

Let us know if any of those work for you.  Thanks.
Greg Kick
Java Core Libraries Team

Nathan Bryant

unread,
Jan 10, 2013, 9:47:30 PM1/10/13
to guava-...@googlegroups.com

RangeSet is nice to see. I did something similar, not too long ago, that was backed by a j.u.BitSet

Your RangeSet has this, therefore it should implement Predicate:

public interface RangeSet<C extends Comparable> {
 
  // Query methods

  /**
   * Determines whether any of this range set's member ranges contains {@code value}.
   */
  boolean contains(C value);

Louis Wasserman

unread,
Jan 11, 2013, 1:57:09 AM1/11/13
to Nathan Bryant, guava-discuss
We considered and rejected the idea, I believe.  Predicates should be immutable; RangeSet isn't, not necessarily.

Martin Steiger

unread,
Jan 11, 2013, 8:46:16 AM1/11/13
to guava-...@googlegroups.com, Nathan Bryant
Thank you all for your feedback.

@kevinb I see your point that it can hardly be defined as a valid pair of Cut<C> instances.
Still, being a corner case, I think that Ranges.none() could have equal right for existance as Ranges().all() does.

What do you think of the following simple implementation?

  /** Returns a range that contains no value of type {@code C}. */
  public static <C extends Comparable<?>> Range<C> none() {
    return create(Cut.<C>aboveAll(), Cut.<C>belowAll());
  }

It uses an invalid combination of Cut<C> to create an "invalid" range.
I could not test it (throws IllArgEx), but I assume it would be consistent with the other Ranges and inherently give correct results for all method calls.

The question is rather academic, I can achieve similar results with Optional<Range<C>> or other proposed methods (thanks @gregoryk)

Kevin Bourrillion

unread,
Jan 11, 2013, 10:41:48 AM1/11/13
to Martin Steiger, guava-...@googlegroups.com, Nathan Bryant
On Fri, Jan 11, 2013 at 5:46 AM, Martin Steiger <goo...@martin-steiger.de> wrote:
Thank you all for your feedback.

@kevinb I see your point that it can hardly be defined as a valid pair of Cut<C> instances.
Still, being a corner case, I think that Ranges.none() could have equal right for existance as Ranges().all() does.

If that were true, we would have done it.  It doesn't work.

 
What do you think of the following simple implementation?

  /** Returns a range that contains no value of type {@code C}. */
  public static <C extends Comparable<?>> Range<C> none() {
    return create(Cut.<C>aboveAll(), Cut.<C>belowAll());
  }

Changing the fundamental assumption that lowerCut <= upperCut would break uncountable things. And I would no longer be able to explain to anyone what a Range really is.

Ray Conner

unread,
Jan 11, 2013, 5:11:55 PM1/11/13
to guava-...@googlegroups.com, Nathan Bryant
Of the approaches mentioned in this thread, and given your original problem statement, I think Optional<Range<C>> is your best option. If absent, that explicitly says "no range", as opposed to "empty range". Given your problem of returning the range spanning a list of input ranges, that seems the most appropriate answer when the input list is empty.

For modeling an actual empty range, I think Greg Kick's first option of (a..a] or [a..a) is the right answer. It already works, and the API methods behave consistently without having to deal with special cases, and without surprising the user.

- Ray A. Conner
Reply all
Reply to author
Forward
0 new messages