API design question on Ints.tryParse()

269 views
Skip to first unread message

Michael Bolin

unread,
Oct 23, 2013, 7:03:55 PM10/23/13
to guava-...@googlegroups.com
Ints.tryParse() returns an Integer and does not declare any exceptions. This seems very un-Guava-y to me, so I'm curious what the arguments were around this API (yes, I do see that it is @Beta).

Arguably Integer.parseInt() is annoying because it throws NumberFormatException in the event of a failure. However, NumberFormatException is an unchecked exception, so this is not particularly burdensome. When things go according to plan, Integer.parseInt() will return a primitive int type, which seems good.

Ints.tryParse() does not throw an exception. I suppose someone argued that this makes it more convenient to check whether the parse was successful. But consider the following examples:

    String inputString = null;
    int meaning = Ints.tryParse(inputString);

and:

    String inputString = "meaning of life";
    int meaning = Ints.tryParse(inputString);

both of these throw a NullPointerException on the second line. That seems a bit unfortunate to me: now you're getting a NullPointerException whereas the real problem is a NumberFormatException. Using the JDK API seems better since at least you would get the appropriate exception.

Though if you do want to go in this direction (never throw), then why not make the return type Optional<Integer>? The only obvious downside to me (as compared to returning Integer) is the creation of an extra object. Though the current return type is Integer instead of int, so you could argue that someone who was memory conscious would already be using Integer.parseInt() in the first place.

Curious,
Michael

Louis Wasserman

unread,
Oct 23, 2013, 7:16:32 PM10/23/13
to Michael Bolin, guava-discuss
To be clear, I'd say we absolutely don't recommend using Ints.tryParse universally in place of Integer.parseInt.  Ints.tryParse is definitely intended to be used only when you're expecting non-integer input in the normal course of events, as opposed to exceptions, which should be used in exceptional cases.  It should definitely be used only when you're actually doing the null check; it shouldn't just be throwing NPEs.

The use of Optional is a valid point, and I haven't been able to find where that discussion happened.  FWIW, though, I can see the argument that if the point is avoiding the performance overhead of an exception, then it makes sense to avoid the overhead of Optional while you're at it.
--
--
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")
---
You received this message because you are subscribed to the Google Groups "guava-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to guava-discus...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/guava-discuss/bf68f14f-d684-4ba9-89c8-e6afac91324a%40googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Blair Zajac

unread,
Oct 23, 2013, 7:26:10 PM10/23/13
to guava-...@googlegroups.com
On 10/23/2013 04:16 PM, Louis Wasserman wrote:
> To be clear, I'd say we absolutely don't recommend using Ints.tryParse
> universally in place of Integer.parseInt. Ints.tryParse is definitely
> intended to be used only when you're expecting non-integer input in the
> normal course of events, as opposed to exceptions, which should be used
> in exceptional cases. It should definitely be used only when you're
> actually doing the null check; it shouldn't just be throwing NPEs.
>
> The use of Optional is a valid point, and I haven't been able to find
> where that discussion happened. FWIW, though, I can see the argument
> that if the point is avoiding the performance overhead of an exception,
> then it makes sense to avoid the overhead of Optional while you're at it.

What is the overhead difference between an exception versus constructing
an Optional? I would think the exception is much more expensive and I
would be happy with always returning an Optional (as that's what we do
as Scala programmers ;) )

Blair

Louis Wasserman

unread,
Oct 23, 2013, 7:28:14 PM10/23/13
to Blair Zajac, guava-discuss
The point is that both Optional and an exception have more overhead than a @Nullable result?  Though obviously Optional has much less added overhead.
--
--
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")
--- You received this message because you are subscribed to the Google Groups "guava-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to guava-discuss+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/guava-discuss/52685B12.5090009%40orcaware.com.

Blair Zajac

unread,
Oct 23, 2013, 7:58:41 PM10/23/13
to Louis Wasserman, guava-discuss
Right, but how much? People may be willing to take a Optional
construction if its 10x cheaper than constructing and throwing an exception.

Blair

On 10/23/2013 04:28 PM, Louis Wasserman wrote:
> The point is that both Optional and an exception have more overhead than
> a @Nullable result? Though obviously Optional has much less added overhead.
>
> Louis Wasserman
> wasserm...@gmail.com <mailto:wasserm...@gmail.com>

Martin Grajcar

unread,
Oct 23, 2013, 8:34:47 PM10/23/13
to guava-...@googlegroups.com
On Thu, Oct 24, 2013 at 1:58 AM, Blair Zajac <bl...@orcaware.com> wrote:
Right, but how much?  People may be willing to take a Optional construction if its 10x cheaper than constructing and throwing an exception.

With respect to memory, I'd say that it's about twice as expensive as using nullable Integer since you need two small objects instead of one. With respect to time, it's a bimorphic virtual call vs. null check, so again at least a factor of two (but probably negligible when compared to the parsing). In case the parsing failed, it's memory-wise one object to zero.

I guess Optional is more 10x cheaper than the exception. However, there might be people wanting the maximum speed possible.

Michael Bolin

unread,
Oct 24, 2013, 3:21:19 PM10/24/13
to guava-...@googlegroups.com
Ever since I accidentally compared two Long objects with == instead of .equals(), I try to convert a Long to a long as quickly as possible. I feel like most of the time when you see a wrapper type in use instead of a primitive, it is can be traced to a side-effect from using generics rather than a developer who wanted to leverage its nullability.

Guava is outspokenly anti-null. Optional seems to underscore that point. The existence of Optional implies that Guava (or at least one rogue functional programmer with commit access to Guava) thinks that it is frequently a win to pay the small cost of extra memory rather than open everyone up to a potential NPE. That's why the current API seems incongruous to me.

Kevin Bourrillion

unread,
Oct 24, 2013, 3:46:59 PM10/24/13
to Michael Bolin, guava-discuss
Hey Michael! Been a while.

On Thu, Oct 24, 2013 at 12:21 PM, Michael Bolin <boli...@gmail.com> wrote:

Guava is outspokenly anti-null. Optional seems to underscore that point. The existence of Optional implies that Guava (or at least one rogue functional programmer with commit access to Guava) thinks that....

You're wrong and you're right.

Guava is "anti-the-many-disadvantages-of-null", which we feel keenly, but I don't like the characterization of "anti-null". Null is just a thing that is good for what it's good for.

And our primary motivation for adding Optional was not to be everyone's replacement for nullability. It had much more to do with addressing these two use cases (listed in its javadoc):
  • To distinguish between "unknown" (for example, not present in a map) and "known to have no value" (present in the map, with value Optional.absent())
  • To wrap nullable references for storage in a collection that does not support null (though there are several other approaches to this that should be considered first)
It's not that it's wrong to use Optional<T> as a general-purpose replacement for @Nullable T, necessarily; I think there's a lot that's good about that. It just comes up over and over again that people think that That's What Optional Is For. Sigh.

Now on the question of why tryParse() returns null, it was because

(a) double-wrapping an int first in an Integer and then in an Optional just felt gross and wrong (especially to Josh, as I recall), and
(b) we weren't excited to start adding OptionalInt, OptionalLong, etc.
(c) returning null felt about equally gross and wrong, but definitely seemed more defensible as being conventional, "normal", and clearly what the JDK method would do if it existed.

HTH!

 
On Wednesday, October 23, 2013 5:34:47 PM UTC-7, Martin Grajcar wrote:
On Thu, Oct 24, 2013 at 1:58 AM, Blair Zajac <bl...@orcaware.com> wrote:
Right, but how much?  People may be willing to take a Optional construction if its 10x cheaper than constructing and throwing an exception.

With respect to memory, I'd say that it's about twice as expensive as using nullable Integer since you need two small objects instead of one. With respect to time, it's a bimorphic virtual call vs. null check, so again at least a factor of two (but probably negligible when compared to the parsing). In case the parsing failed, it's memory-wise one object to zero.

I guess Optional is more 10x cheaper than the exception. However, there might be people wanting the maximum speed possible.

--
--
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")
---
You received this message because you are subscribed to the Google Groups "guava-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to guava-discus...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/guava-discuss/a0eb2ab7-6af0-41af-92f1-a97796bd931e%40googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.



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

Michael Bolin

unread,
Oct 28, 2013, 9:17:59 PM10/28/13
to guava-...@googlegroups.com, Michael Bolin
Hi Kevin: thanks for the thorough answer!

FWIW, it is true that http://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained explains that Guava isn't exactly "anti-null," but the quotes on the top of the page seem to suggest it :) I've been curious how hard it would be to write a Proguard-like pass over .class files that would replace Optionals with Nullables so that you could get the compile-time benefits without paying the runtime memory costs. (I say Proguard-like, since it would presumably have to be a whole-program optimization.)

Thanks again,
Michael
Reply all
Reply to author
Forward
0 new messages