Checked exceptions within Block<T>

Zhong Yu zhong.j.yu at gmail.com
Sat Jan 12 10:10:57 PST 2013


Cool. I'm getting that you guys have better future plans, so you
resist stupid short term fixes.

On Sat, Jan 12, 2013 at 11:49 AM, Brian Goetz <brian.goetz at oracle.com> wrote:
> Yes, you'd have to provide your own exceptional SAMs.  But then lambda
> conversion would work fine with them.
>
> The EG discussed additional language and library support for this problem,
> and in the end felt that this was a bad cost/benefit tradeoff.
>
> Library-based solutions cause a 2x explosion in SAM types (exceptional vs
> not), which interact badly with existing combinatorial explosions for
> primitive specialization.
>
> The available language-based solutions were losers from a complexity/value
> tradeoff.  Though there are some alternative solutions we are going to
> continue to explore -- though clearly not for 8 and probably not for 9
> either.
>
> In the meantime, you have the tools to do what you want.  I get that you
> prefer we provide that last mile for you (and, secondarily, your request is
> really a thinly-veiled request for "why don't you just give up on checked
> exceptions already"), but I think the current state lets you get your job
> done.
>
>
> On 1/12/2013 12:35 PM, Zhong Yu wrote:
>>
>> 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