Function and Predicate parameter ambiguous?
Using Java 8, I get a compiler error for the following code:
public class Ambiguous {
public static void call() {
SomeDataClass data = new SomeDataClass();
callee(data, SomeDataClass::getString);
// compiler errors:
// 1. at callee method name:
// The method callee(SomeDataClass, Function<SomeDataClass,String>) is ambiguous for the type Ambiguous
// 2. at lambda:
// Type mismatch: cannot convert from boolean to String
callee(data, d -> d.getRandom() > 0.5);
}
public static void callee(SomeDataClass data, Function<SomeDataClass, String> extractString) {
System.out.println(extractString.apply(data));
}
public static void callee(SomeDataClass data, Predicate<SomeDataClass> check) {
System.out.println(check.test(data));
}
}
// token data class
final class SomeDataClass {
public String getString() {
return "string";
}
public final double getRandom() {
return Math.random();
}
}
So essentially the compiler says "I know you return boolean but you shouldn't, and if you don't I'm not sure what method to use" instead of "oh you're returning boolean, you must mean the Predicate version of the method"? How does this confusion get created?
I'd understand if Predicate<T> extends Function<T, Boolean> (so they have a common Type) but that's not the case.
I do know how to fix it; it's fine if I do
callee(data, (Predicate<SomeDataClass>) d -> d.getRandom() > 0.5);
but I'm curious what causes it.
java java-8 functional-programming
add a comment |
Using Java 8, I get a compiler error for the following code:
public class Ambiguous {
public static void call() {
SomeDataClass data = new SomeDataClass();
callee(data, SomeDataClass::getString);
// compiler errors:
// 1. at callee method name:
// The method callee(SomeDataClass, Function<SomeDataClass,String>) is ambiguous for the type Ambiguous
// 2. at lambda:
// Type mismatch: cannot convert from boolean to String
callee(data, d -> d.getRandom() > 0.5);
}
public static void callee(SomeDataClass data, Function<SomeDataClass, String> extractString) {
System.out.println(extractString.apply(data));
}
public static void callee(SomeDataClass data, Predicate<SomeDataClass> check) {
System.out.println(check.test(data));
}
}
// token data class
final class SomeDataClass {
public String getString() {
return "string";
}
public final double getRandom() {
return Math.random();
}
}
So essentially the compiler says "I know you return boolean but you shouldn't, and if you don't I'm not sure what method to use" instead of "oh you're returning boolean, you must mean the Predicate version of the method"? How does this confusion get created?
I'd understand if Predicate<T> extends Function<T, Boolean> (so they have a common Type) but that's not the case.
I do know how to fix it; it's fine if I do
callee(data, (Predicate<SomeDataClass>) d -> d.getRandom() > 0.5);
but I'm curious what causes it.
java java-8 functional-programming
3
FYI, this issue is addressed in JEP-302 and will be hopefully fixed in some of the future Java versions: openjdk.java.net/jeps/302 (see Optional: Better disambiguation for functional expression)
– ZhekaKozlov
May 4 '18 at 7:51
@ZhekaKozlov excellent! I could not remember the JEP number
– Eugene
May 4 '18 at 7:53
add a comment |
Using Java 8, I get a compiler error for the following code:
public class Ambiguous {
public static void call() {
SomeDataClass data = new SomeDataClass();
callee(data, SomeDataClass::getString);
// compiler errors:
// 1. at callee method name:
// The method callee(SomeDataClass, Function<SomeDataClass,String>) is ambiguous for the type Ambiguous
// 2. at lambda:
// Type mismatch: cannot convert from boolean to String
callee(data, d -> d.getRandom() > 0.5);
}
public static void callee(SomeDataClass data, Function<SomeDataClass, String> extractString) {
System.out.println(extractString.apply(data));
}
public static void callee(SomeDataClass data, Predicate<SomeDataClass> check) {
System.out.println(check.test(data));
}
}
// token data class
final class SomeDataClass {
public String getString() {
return "string";
}
public final double getRandom() {
return Math.random();
}
}
So essentially the compiler says "I know you return boolean but you shouldn't, and if you don't I'm not sure what method to use" instead of "oh you're returning boolean, you must mean the Predicate version of the method"? How does this confusion get created?
I'd understand if Predicate<T> extends Function<T, Boolean> (so they have a common Type) but that's not the case.
I do know how to fix it; it's fine if I do
callee(data, (Predicate<SomeDataClass>) d -> d.getRandom() > 0.5);
but I'm curious what causes it.
java java-8 functional-programming
Using Java 8, I get a compiler error for the following code:
public class Ambiguous {
public static void call() {
SomeDataClass data = new SomeDataClass();
callee(data, SomeDataClass::getString);
// compiler errors:
// 1. at callee method name:
// The method callee(SomeDataClass, Function<SomeDataClass,String>) is ambiguous for the type Ambiguous
// 2. at lambda:
// Type mismatch: cannot convert from boolean to String
callee(data, d -> d.getRandom() > 0.5);
}
public static void callee(SomeDataClass data, Function<SomeDataClass, String> extractString) {
System.out.println(extractString.apply(data));
}
public static void callee(SomeDataClass data, Predicate<SomeDataClass> check) {
System.out.println(check.test(data));
}
}
// token data class
final class SomeDataClass {
public String getString() {
return "string";
}
public final double getRandom() {
return Math.random();
}
}
So essentially the compiler says "I know you return boolean but you shouldn't, and if you don't I'm not sure what method to use" instead of "oh you're returning boolean, you must mean the Predicate version of the method"? How does this confusion get created?
I'd understand if Predicate<T> extends Function<T, Boolean> (so they have a common Type) but that's not the case.
I do know how to fix it; it's fine if I do
callee(data, (Predicate<SomeDataClass>) d -> d.getRandom() > 0.5);
but I'm curious what causes it.
java java-8 functional-programming
java java-8 functional-programming
asked May 4 '18 at 7:37
daniudaniu
7,68821635
7,68821635
3
FYI, this issue is addressed in JEP-302 and will be hopefully fixed in some of the future Java versions: openjdk.java.net/jeps/302 (see Optional: Better disambiguation for functional expression)
– ZhekaKozlov
May 4 '18 at 7:51
@ZhekaKozlov excellent! I could not remember the JEP number
– Eugene
May 4 '18 at 7:53
add a comment |
3
FYI, this issue is addressed in JEP-302 and will be hopefully fixed in some of the future Java versions: openjdk.java.net/jeps/302 (see Optional: Better disambiguation for functional expression)
– ZhekaKozlov
May 4 '18 at 7:51
@ZhekaKozlov excellent! I could not remember the JEP number
– Eugene
May 4 '18 at 7:53
3
3
FYI, this issue is addressed in JEP-302 and will be hopefully fixed in some of the future Java versions: openjdk.java.net/jeps/302 (see Optional: Better disambiguation for functional expression)
– ZhekaKozlov
May 4 '18 at 7:51
FYI, this issue is addressed in JEP-302 and will be hopefully fixed in some of the future Java versions: openjdk.java.net/jeps/302 (see Optional: Better disambiguation for functional expression)
– ZhekaKozlov
May 4 '18 at 7:51
@ZhekaKozlov excellent! I could not remember the JEP number
– Eugene
May 4 '18 at 7:53
@ZhekaKozlov excellent! I could not remember the JEP number
– Eugene
May 4 '18 at 7:53
add a comment |
1 Answer
1
active
oldest
votes
This can be simplified a bit for clarity:
public static void m(Predicate<Integer> predicate){
}
public static void m(Function<Integer, String> function){
}
And calling it with:
m(i -> "test")
What do you think will happen? Same thing as in your question.
Compiler here has to know the method in order to find the target type, but it needs to know the target type in order to resolve the method (it's like a deadlock).
When you add a cast to Predicate..., you are creating an explicit target type, return type of which is taken into consideration for method overloading as far as I understand.
1
But I can see thati -> "test"is not aPredicate, so why can't the compiler? Type erasure doesn't explain it.
– slim
May 4 '18 at 7:51
1
@slim I can see != compiler can see, this is a trivial example which could probably be made to work, but there are others that are not that easy I guess
– Eugene
May 4 '18 at 7:52
1
Sure, but a satisfactory answer is going to explain the limitations of what the compiler (or rather the language spec) can infer about the type, and why. Great job simplifying the question though.
– slim
May 4 '18 at 7:54
1
@daniu did you read this? stackoverflow.com/a/21951311/1059372
– Eugene
May 4 '18 at 9:54
1
@eugene yes that was very enlightening, thank you. Forgot to set to answered, sorry.
– daniu
May 10 '18 at 9:25
|
show 6 more comments
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f50169639%2ffunction-and-predicate-parameter-ambiguous%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
This can be simplified a bit for clarity:
public static void m(Predicate<Integer> predicate){
}
public static void m(Function<Integer, String> function){
}
And calling it with:
m(i -> "test")
What do you think will happen? Same thing as in your question.
Compiler here has to know the method in order to find the target type, but it needs to know the target type in order to resolve the method (it's like a deadlock).
When you add a cast to Predicate..., you are creating an explicit target type, return type of which is taken into consideration for method overloading as far as I understand.
1
But I can see thati -> "test"is not aPredicate, so why can't the compiler? Type erasure doesn't explain it.
– slim
May 4 '18 at 7:51
1
@slim I can see != compiler can see, this is a trivial example which could probably be made to work, but there are others that are not that easy I guess
– Eugene
May 4 '18 at 7:52
1
Sure, but a satisfactory answer is going to explain the limitations of what the compiler (or rather the language spec) can infer about the type, and why. Great job simplifying the question though.
– slim
May 4 '18 at 7:54
1
@daniu did you read this? stackoverflow.com/a/21951311/1059372
– Eugene
May 4 '18 at 9:54
1
@eugene yes that was very enlightening, thank you. Forgot to set to answered, sorry.
– daniu
May 10 '18 at 9:25
|
show 6 more comments
This can be simplified a bit for clarity:
public static void m(Predicate<Integer> predicate){
}
public static void m(Function<Integer, String> function){
}
And calling it with:
m(i -> "test")
What do you think will happen? Same thing as in your question.
Compiler here has to know the method in order to find the target type, but it needs to know the target type in order to resolve the method (it's like a deadlock).
When you add a cast to Predicate..., you are creating an explicit target type, return type of which is taken into consideration for method overloading as far as I understand.
1
But I can see thati -> "test"is not aPredicate, so why can't the compiler? Type erasure doesn't explain it.
– slim
May 4 '18 at 7:51
1
@slim I can see != compiler can see, this is a trivial example which could probably be made to work, but there are others that are not that easy I guess
– Eugene
May 4 '18 at 7:52
1
Sure, but a satisfactory answer is going to explain the limitations of what the compiler (or rather the language spec) can infer about the type, and why. Great job simplifying the question though.
– slim
May 4 '18 at 7:54
1
@daniu did you read this? stackoverflow.com/a/21951311/1059372
– Eugene
May 4 '18 at 9:54
1
@eugene yes that was very enlightening, thank you. Forgot to set to answered, sorry.
– daniu
May 10 '18 at 9:25
|
show 6 more comments
This can be simplified a bit for clarity:
public static void m(Predicate<Integer> predicate){
}
public static void m(Function<Integer, String> function){
}
And calling it with:
m(i -> "test")
What do you think will happen? Same thing as in your question.
Compiler here has to know the method in order to find the target type, but it needs to know the target type in order to resolve the method (it's like a deadlock).
When you add a cast to Predicate..., you are creating an explicit target type, return type of which is taken into consideration for method overloading as far as I understand.
This can be simplified a bit for clarity:
public static void m(Predicate<Integer> predicate){
}
public static void m(Function<Integer, String> function){
}
And calling it with:
m(i -> "test")
What do you think will happen? Same thing as in your question.
Compiler here has to know the method in order to find the target type, but it needs to know the target type in order to resolve the method (it's like a deadlock).
When you add a cast to Predicate..., you are creating an explicit target type, return type of which is taken into consideration for method overloading as far as I understand.
edited May 4 '18 at 8:58
answered May 4 '18 at 7:44
EugeneEugene
70.7k9102169
70.7k9102169
1
But I can see thati -> "test"is not aPredicate, so why can't the compiler? Type erasure doesn't explain it.
– slim
May 4 '18 at 7:51
1
@slim I can see != compiler can see, this is a trivial example which could probably be made to work, but there are others that are not that easy I guess
– Eugene
May 4 '18 at 7:52
1
Sure, but a satisfactory answer is going to explain the limitations of what the compiler (or rather the language spec) can infer about the type, and why. Great job simplifying the question though.
– slim
May 4 '18 at 7:54
1
@daniu did you read this? stackoverflow.com/a/21951311/1059372
– Eugene
May 4 '18 at 9:54
1
@eugene yes that was very enlightening, thank you. Forgot to set to answered, sorry.
– daniu
May 10 '18 at 9:25
|
show 6 more comments
1
But I can see thati -> "test"is not aPredicate, so why can't the compiler? Type erasure doesn't explain it.
– slim
May 4 '18 at 7:51
1
@slim I can see != compiler can see, this is a trivial example which could probably be made to work, but there are others that are not that easy I guess
– Eugene
May 4 '18 at 7:52
1
Sure, but a satisfactory answer is going to explain the limitations of what the compiler (or rather the language spec) can infer about the type, and why. Great job simplifying the question though.
– slim
May 4 '18 at 7:54
1
@daniu did you read this? stackoverflow.com/a/21951311/1059372
– Eugene
May 4 '18 at 9:54
1
@eugene yes that was very enlightening, thank you. Forgot to set to answered, sorry.
– daniu
May 10 '18 at 9:25
1
1
But I can see that
i -> "test" is not a Predicate, so why can't the compiler? Type erasure doesn't explain it.– slim
May 4 '18 at 7:51
But I can see that
i -> "test" is not a Predicate, so why can't the compiler? Type erasure doesn't explain it.– slim
May 4 '18 at 7:51
1
1
@slim I can see != compiler can see, this is a trivial example which could probably be made to work, but there are others that are not that easy I guess
– Eugene
May 4 '18 at 7:52
@slim I can see != compiler can see, this is a trivial example which could probably be made to work, but there are others that are not that easy I guess
– Eugene
May 4 '18 at 7:52
1
1
Sure, but a satisfactory answer is going to explain the limitations of what the compiler (or rather the language spec) can infer about the type, and why. Great job simplifying the question though.
– slim
May 4 '18 at 7:54
Sure, but a satisfactory answer is going to explain the limitations of what the compiler (or rather the language spec) can infer about the type, and why. Great job simplifying the question though.
– slim
May 4 '18 at 7:54
1
1
@daniu did you read this? stackoverflow.com/a/21951311/1059372
– Eugene
May 4 '18 at 9:54
@daniu did you read this? stackoverflow.com/a/21951311/1059372
– Eugene
May 4 '18 at 9:54
1
1
@eugene yes that was very enlightening, thank you. Forgot to set to answered, sorry.
– daniu
May 10 '18 at 9:25
@eugene yes that was very enlightening, thank you. Forgot to set to answered, sorry.
– daniu
May 10 '18 at 9:25
|
show 6 more comments
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f50169639%2ffunction-and-predicate-parameter-ambiguous%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown

3
FYI, this issue is addressed in JEP-302 and will be hopefully fixed in some of the future Java versions: openjdk.java.net/jeps/302 (see Optional: Better disambiguation for functional expression)
– ZhekaKozlov
May 4 '18 at 7:51
@ZhekaKozlov excellent! I could not remember the JEP number
– Eugene
May 4 '18 at 7:53