Checked exceptions within Block<T>

Zhong Yu zhong.j.yu at gmail.com
Sat Jan 12 09:35:29 PST 2013


You are probably mistaken here, since b.accept(e) does not throw
checked exceptions.

If you what you really meant was a solution like Peter Levart's,
should it (BlockEx) be included in standard lib? Since it might be
useful to a wide audience.

Zhong Yu

On Sat, Jan 12, 2013 at 11:21 AM, Brian Goetz <brian.goetz at oracle.com> wrote:
> Or you could write your own trivial combinator:
>
> static<T> Block<T> exceptionWrappingBlock(Block<T> b) {
>     return e -> {
>         try { b.accept(e); }
>         catch (Exception e) { throw new RTE(e); }
>     };
> }
>
> You can write it once, in less that the time it took to write your original
> e-mail.  And similarly once for each kind of SAM you use.
>
> I'd rather we look at this as "glass 99% full" rather than the alternative.
> Not all problems require new language features as solutions.  (Not to
> mention that new language features always causes new problems.)
>
>
>
> On 1/12/2013 11:03 AM, Zhong Yu wrote:
>>
>> I too have this problem, since we have lots of code throwing checked
>> exceptions, it's a challenge to wrap them in functional interfaces
>> that do not throw.
>>
>> If the solution is to smuggle checked exception as unchecked, JDK
>> should provide a standard class for that specific purpose, or
>> everybody will be forced to invent their own.
>>
>> A better solution is probably having varying exceptions
>>
>>      interface Block<T, E extends Throwable>
>>          void apply(T input) throws E;
>>
>>      <T,E extends Throwable> void forEach(Block<T,E> block) throws E
>>
>> this is very ugly though; I'd dream the language could make it simpler
>> like
>>
>>      interface Block<T>
>>          void apply(T input) throws ?;
>>          // abstract method; throws E; add E to interface.
>>
>>      <T> void forEach(Block<T> block) throws ? { ... }
>>      // non-abstract method; throws E; add E to method.
>>
>>
>> Zhong Yu
>>
>> On Fri, Jan 11, 2013 at 10:12 PM, 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