Checked exceptions within Block<T>
Ricky Clarkson
ricky.clarkson at gmail.com
Sat Jan 12 07:09:02 PST 2013
This was one of the use cases the original BGGA proposal took into
account. You'll also find refactoring difficult if there's a return,
break, continue or write to a local variable or parameter within the for's
block.
Assuming those avenues are closed it would be good to make things like
Optional be Iterable (there are precedents for this in other libraries but
it's not universal).
On Jan 12, 2013 1:13 AM, "Michael Hixson" <michael.hixson at gmail.com> wrote:
> This is a bit of feedback for the lambda snapshots. It's not really
> suggesting any changes or reporting bugs, but rather describing
> difficulties I had. Hopefully this is the right mailing list for this
> sort of thing.
>
> --------------------------------
>
> An issue that came up repeatedly was that I wanted refactor code like this:
>
> for (Value value : values) {
> ...
> }
>
> Into this:
>
> values.forEach(value -> {
> ...
> });
>
> But I couldn't because the "..." could throw a checked exception. I
> worked around this in two ways:
>
> (a) Don't refactor the code.
> (b) Change whatever is throwing the checked exception to throw a
> runtime exception instead.
>
> Option (a) was not so bad if my "values" object was an Iterable. It
> was worse when my values were a Map, a Stream, or an Optional. To
> compare:
>
> for (Map.Entry<Key, Value> entry : values.entrySet()) {
> Key key = entry.getKey();
> Value value = entry.getValue();
> ...
> }
>
> values.forEach((key, value) -> {
> ...
> });
>
> for (Iterator iterator =
> values.stream().filter(predicate).map(function).iterator();
> iterator.hasNext();) {
> Value value = iterator.next();
> ...
> }
>
> values.stream().filter(predicate).map(function).forEach(value -> {
> ...
> });
>
> Optional<Value> optionalValue = somethingThatGivesAnOptional();
> if (optionalValue.isPresent()) {
> Value value = optionalValue.get();
> ...
> }
>
> somethingThatGivesAnOptional().ifPresent(value -> {
> ...
> });
>
> In one case (really several cases that relied on the same utility)
> that was enough to drive me to option (b).
>
> Option (b) allowed me to use the new lambda goodness but made me
> slightly uncomfortable. The utility in question could write values in
> CSV format to an Appendable. Since Appendable can throw IOExceptions,
> I initially had the utility methods throw IOException. To make it
> lambda-friendly I changed all its methods to look like this:
>
> try {
> ...
> } catch (IOException e) {
> throw new UncheckedIOException(e);
> }
>
> This was fine because I wasn't catching any IOExceptions that occurred
> in the first place (this code was running in response to a web
> request, and if an exception occurred the framework would handle it
> and show an error page). But I felt that it made my CSV utility a
> little more "dangerous" for general use. This is all sort of
> hand-wavey, but I don't like that the utility now potentially throws
> runtime exceptions when there's not a programmer error and when there
> might be a reasonable way to recover. Plus it is additional code in
> my utility class, and good thing it is my class and not someone
> else's.
>
> What I really wanted to do was leave in the checked exceptions *and*
> use the lambda forEach/ifPresent forms.
>
> -Michael
>
>
More information about the lambda-dev
mailing list