[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openjdk-lambda-dev
Subject:    =?utf-8?Q?Re:_Overload_resolution_chooses_type_that's_invalid, _too_genera?= =?utf-8?Q?l_or_not_at_a
From:       Timo_Kinnunen <timo.kinnunen () gmail ! com>
Date:       2014-01-14 0:17:52
Message-ID: 52d673c7.81620e0a.0802.ffffc293 () mx ! google ! com
[Download RAW message or body]

Hi, 




Re: "I know what you want is to define two identical methods that simply vary in the \
exceptions thrown.  The problem is that, for all the compiler knows, the two methods \
do dramatically different things, and the compiler is interested in minimizing the \
risk of accidentally getting the wrong behavior.

(What you mean, by the way, is "choose the one that throws the least ***but still \
declares all the exceptions thrown by the lambda body***".)"




It isn't the compiler's place to be the decider of which same-but-different things \
are OK and which are not. There is a dramatic difference between \
System.out.println("10") copying 4 bytes in memory and System.out.println(10) doing \
integer divisions yet there is no need for claiming ambiguity, because the difference \
is in implementation that the compiler can reason about and not in the Javadoc which \
the compiler doesn't understand anyway.




And no, I don't mean that. "But still declares all the checked exceptions" has to be \
checked anyway, regardless of how that type was arrived at. Explicitly listing more \
exceptions than the lambda block body can throw is valid, maybe with a warning. Doing \
this mandatory check on two types instead of one and then not picking a one that \
doesn't violate the spec would be illogical.





Re: "The simplest solution is to simply give the methods different names."




This would push the problem to the users of my API and is not the solution, because I \
am the user of my API.




Re: "May I suggest that what you really mean to say is this: the language doesn't \
handle exception transparency for lambda expressions very well?  If so, then yes, we \
know, and have some ideas about how to address that problem, preferably entirely \
sidestepping overloading and generics."


Not just for lambda expressions, I found that to be the case in regular methods as \
well, when implementing exception wrappers and unwrappers around Stream pipeline \
stages. Things like a way to catch and throw exceptions generically and being able to \
use multi-catch syntax in a throws specification would help, but these are dancing \
around the real problem. 


What is needed is a way to insulate the implementation details of one method A from \
the implementation details of another method B that the method A calls, such that \
whatever happens after this crossover point - exceptions and all - happens as if it \
was the caller of method A who called method B.


This is Guy Steele's tail-call optimization, I've just realized.






-- 
Have a nice day,
Timo.

Sent from Windows Mail





From: Dan Smith
Sent: ‎Tuesday‎, ‎January‎ ‎14‎, ‎2014 ‎00‎:‎12
To: Timo Kinnunen
Cc: lambda-dev@openjdk.java.net





On Jan 10, 2014, at 4:05 AM, Timo Kinnunen <timo.kinnunen@gmail.com> wrote:

> Hi,
> 
> In the case where the difference between two target types is only that one
> of them has a generic throws declaration, this leads to ambiguity even when
> choosing the wrong one would be a compile error.
> 
> This seems to be working as specified, with the goal to make the result
> more stable and predictable, but I would argue the actual result is just
> the opposite. Why not try each candidate in turn and choose the one that
> throws the least?

"Do exactly what I want" and "be stable and predictable" are often in tension when \
the compiler is asked to infer something.

You're right that the treatment of exceptions thrown by a lambda body in overload \
resolution is by design, with the intent that ambiguity errors will prompt the user \
to be more explicit about what he wants (and prompt API designers to avoid these \
subtle overloads).

I know what you want is to define two identical methods that simply vary in the \
exceptions thrown.  The problem is that, for all the compiler knows, the two methods \
do dramatically different things, and the compiler is interested in minimizing the \
risk of accidentally getting the wrong behavior.

(What you mean, by the way, is "choose the one that throws the least ***but still \
declares all the exceptions thrown by the lambda body***".)

> I have found a workaround. By making some small artificial changes (notice
> a pattern?) to one method that makes its signature less readable I can
> affect changes in which rounds each method participates. This allows things
> to compile but I lose some useful information about which lambdas actually
> don't throw exceptions. I have found a lot of variations  to choose from
> but not the one that produces the optimal result so far.

The simplest solution is to simply give the methods different names.

> I'd like the compiler to choose the optimal method automatically, because
> it knows the types better than I do.

The problem is that the compiler doesn't know whether you really mean to throw an \
exception, or whether you intend to catch it but you forgot.  And it doesn't know \
whether you really meant to change the program's behavior when you commented out a \
line that happened to throw an exception.

> Absent that, I'd like it to give each
> method its due consideration, because that's why I added the overloads in
> the first place. Absent that, I'd like some API for saying which order the
> overloaded methods should be tried. And absent that, I'd like to have some
> official documentation on how to correctly target methods to a particular
> round of resolution.

As an API designer, you make one method have priority over another by either i) \
making it more specific than another for expected inputs; or ii) making it applicable \
in an earlier phase for expected inputs.  I acknowledge that you're looking for \
something more; it's not clear that this is a general enough problem to prompt \
language changes.

But in any case, I don't see how this helps.  If you make the method that has a \
non-exception-throwing functional interface parameter more specific than the method \
that has an exception-throwing functional interface parameter, you're just going to \
get compiler errors whenever you have any exceptions.  Both methods will always be \
applicable, because exceptions thrown by a lambda body do not influence method \
applicability.

May I suggest that what you really mean to say is this: the language doesn't handle \
exception transparency for lambda expressions very well?  If so, then yes, we know, \
and have some ideas about how to address that problem, preferably entirely \
sidestepping overloading and generics.

—Dan


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic