Why does .forEach(val -> list.add()) compile whereas .forEach(val -> true) doesn't? [duplicate]












8















This question already has an answer here:




  • Why do Consumers accept lambdas with statement bodies but not expression bodies?

    3 answers



  • Why does a Java method reference with return type match the Consumer interface?

    2 answers




It's better to express this behavior in the code:



List<Integer> list= new ArrayList<>();
Stream.of(1,2,3).forEach(i -> list.add(1)); // COMPILES

Stream.of(1,2,3).forEach(i -> true); // DOES NOT COMPILE!


forEach(...) accepts Consumer, but why does the first example compile if List interface has following signature boolean add(E e)? whereas the second yields:




bad return type in lambda expression: boolean cannot be converted to
void











share|improve this question















marked as duplicate by Aomine java
Users with the  java badge can single-handedly close java questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Dec 15 '18 at 20:20


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.















  • What are you trying to achieve with the second statement?
    – Nicholas K
    Dec 15 '18 at 16:06










  • Hint: Stream.of(1,2,3).forEach(i -> {return list.add(1);}) also doesn't compile. Hint2: What method ( X -> Y mapping) Consumer<T> represents (take a look at abstract method it contains, what type of parameter(s) it accepts and what is its return type)?
    – Pshemo
    Dec 15 '18 at 16:19












  • Instead of simply stating "does not compile", it would be much better if you could show the precise error message you are getting. In particular, at least one answer is operating under the assumption that you are getting a syntax error (although in that case, "does not parse" would be more correct than "does not compile"), but I don't think a syntax error is the problem.
    – Jörg W Mittag
    Dec 15 '18 at 16:19










  • @JörgWMittag The compilation error prints incompatible types: bad return type in lambda expression missing return value. @Pshemo before I started this thread I checked what is the signature is. Consumer.accept(T t) should return void (docs.oracle.com/javase/8/docs/api/java/util/function/…)
    – Leonid Dashko
    Dec 15 '18 at 19:25








  • 1




    @LeonidDashko when I ran this on IntelliJ IDEA I got the error I've included in the post. However, since it's not word for word the same as what you've just mentioned, please consider updating the post with the exact information.
    – Aomine
    Dec 15 '18 at 20:07


















8















This question already has an answer here:




  • Why do Consumers accept lambdas with statement bodies but not expression bodies?

    3 answers



  • Why does a Java method reference with return type match the Consumer interface?

    2 answers




It's better to express this behavior in the code:



List<Integer> list= new ArrayList<>();
Stream.of(1,2,3).forEach(i -> list.add(1)); // COMPILES

Stream.of(1,2,3).forEach(i -> true); // DOES NOT COMPILE!


forEach(...) accepts Consumer, but why does the first example compile if List interface has following signature boolean add(E e)? whereas the second yields:




bad return type in lambda expression: boolean cannot be converted to
void











share|improve this question















marked as duplicate by Aomine java
Users with the  java badge can single-handedly close java questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Dec 15 '18 at 20:20


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.















  • What are you trying to achieve with the second statement?
    – Nicholas K
    Dec 15 '18 at 16:06










  • Hint: Stream.of(1,2,3).forEach(i -> {return list.add(1);}) also doesn't compile. Hint2: What method ( X -> Y mapping) Consumer<T> represents (take a look at abstract method it contains, what type of parameter(s) it accepts and what is its return type)?
    – Pshemo
    Dec 15 '18 at 16:19












  • Instead of simply stating "does not compile", it would be much better if you could show the precise error message you are getting. In particular, at least one answer is operating under the assumption that you are getting a syntax error (although in that case, "does not parse" would be more correct than "does not compile"), but I don't think a syntax error is the problem.
    – Jörg W Mittag
    Dec 15 '18 at 16:19










  • @JörgWMittag The compilation error prints incompatible types: bad return type in lambda expression missing return value. @Pshemo before I started this thread I checked what is the signature is. Consumer.accept(T t) should return void (docs.oracle.com/javase/8/docs/api/java/util/function/…)
    – Leonid Dashko
    Dec 15 '18 at 19:25








  • 1




    @LeonidDashko when I ran this on IntelliJ IDEA I got the error I've included in the post. However, since it's not word for word the same as what you've just mentioned, please consider updating the post with the exact information.
    – Aomine
    Dec 15 '18 at 20:07
















8












8








8


0






This question already has an answer here:




  • Why do Consumers accept lambdas with statement bodies but not expression bodies?

    3 answers



  • Why does a Java method reference with return type match the Consumer interface?

    2 answers




It's better to express this behavior in the code:



List<Integer> list= new ArrayList<>();
Stream.of(1,2,3).forEach(i -> list.add(1)); // COMPILES

Stream.of(1,2,3).forEach(i -> true); // DOES NOT COMPILE!


forEach(...) accepts Consumer, but why does the first example compile if List interface has following signature boolean add(E e)? whereas the second yields:




bad return type in lambda expression: boolean cannot be converted to
void











share|improve this question
















This question already has an answer here:




  • Why do Consumers accept lambdas with statement bodies but not expression bodies?

    3 answers



  • Why does a Java method reference with return type match the Consumer interface?

    2 answers




It's better to express this behavior in the code:



List<Integer> list= new ArrayList<>();
Stream.of(1,2,3).forEach(i -> list.add(1)); // COMPILES

Stream.of(1,2,3).forEach(i -> true); // DOES NOT COMPILE!


forEach(...) accepts Consumer, but why does the first example compile if List interface has following signature boolean add(E e)? whereas the second yields:




bad return type in lambda expression: boolean cannot be converted to
void






This question already has an answer here:




  • Why do Consumers accept lambdas with statement bodies but not expression bodies?

    3 answers



  • Why does a Java method reference with return type match the Consumer interface?

    2 answers








java java-8 compiler-errors java-stream






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 15 '18 at 19:59









Aomine

41.6k74071




41.6k74071










asked Dec 15 '18 at 15:58









Leonid DashkoLeonid Dashko

726611




726611




marked as duplicate by Aomine java
Users with the  java badge can single-handedly close java questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Dec 15 '18 at 20:20


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.






marked as duplicate by Aomine java
Users with the  java badge can single-handedly close java questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Dec 15 '18 at 20:20


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.














  • What are you trying to achieve with the second statement?
    – Nicholas K
    Dec 15 '18 at 16:06










  • Hint: Stream.of(1,2,3).forEach(i -> {return list.add(1);}) also doesn't compile. Hint2: What method ( X -> Y mapping) Consumer<T> represents (take a look at abstract method it contains, what type of parameter(s) it accepts and what is its return type)?
    – Pshemo
    Dec 15 '18 at 16:19












  • Instead of simply stating "does not compile", it would be much better if you could show the precise error message you are getting. In particular, at least one answer is operating under the assumption that you are getting a syntax error (although in that case, "does not parse" would be more correct than "does not compile"), but I don't think a syntax error is the problem.
    – Jörg W Mittag
    Dec 15 '18 at 16:19










  • @JörgWMittag The compilation error prints incompatible types: bad return type in lambda expression missing return value. @Pshemo before I started this thread I checked what is the signature is. Consumer.accept(T t) should return void (docs.oracle.com/javase/8/docs/api/java/util/function/…)
    – Leonid Dashko
    Dec 15 '18 at 19:25








  • 1




    @LeonidDashko when I ran this on IntelliJ IDEA I got the error I've included in the post. However, since it's not word for word the same as what you've just mentioned, please consider updating the post with the exact information.
    – Aomine
    Dec 15 '18 at 20:07




















  • What are you trying to achieve with the second statement?
    – Nicholas K
    Dec 15 '18 at 16:06










  • Hint: Stream.of(1,2,3).forEach(i -> {return list.add(1);}) also doesn't compile. Hint2: What method ( X -> Y mapping) Consumer<T> represents (take a look at abstract method it contains, what type of parameter(s) it accepts and what is its return type)?
    – Pshemo
    Dec 15 '18 at 16:19












  • Instead of simply stating "does not compile", it would be much better if you could show the precise error message you are getting. In particular, at least one answer is operating under the assumption that you are getting a syntax error (although in that case, "does not parse" would be more correct than "does not compile"), but I don't think a syntax error is the problem.
    – Jörg W Mittag
    Dec 15 '18 at 16:19










  • @JörgWMittag The compilation error prints incompatible types: bad return type in lambda expression missing return value. @Pshemo before I started this thread I checked what is the signature is. Consumer.accept(T t) should return void (docs.oracle.com/javase/8/docs/api/java/util/function/…)
    – Leonid Dashko
    Dec 15 '18 at 19:25








  • 1




    @LeonidDashko when I ran this on IntelliJ IDEA I got the error I've included in the post. However, since it's not word for word the same as what you've just mentioned, please consider updating the post with the exact information.
    – Aomine
    Dec 15 '18 at 20:07


















What are you trying to achieve with the second statement?
– Nicholas K
Dec 15 '18 at 16:06




What are you trying to achieve with the second statement?
– Nicholas K
Dec 15 '18 at 16:06












Hint: Stream.of(1,2,3).forEach(i -> {return list.add(1);}) also doesn't compile. Hint2: What method ( X -> Y mapping) Consumer<T> represents (take a look at abstract method it contains, what type of parameter(s) it accepts and what is its return type)?
– Pshemo
Dec 15 '18 at 16:19






Hint: Stream.of(1,2,3).forEach(i -> {return list.add(1);}) also doesn't compile. Hint2: What method ( X -> Y mapping) Consumer<T> represents (take a look at abstract method it contains, what type of parameter(s) it accepts and what is its return type)?
– Pshemo
Dec 15 '18 at 16:19














Instead of simply stating "does not compile", it would be much better if you could show the precise error message you are getting. In particular, at least one answer is operating under the assumption that you are getting a syntax error (although in that case, "does not parse" would be more correct than "does not compile"), but I don't think a syntax error is the problem.
– Jörg W Mittag
Dec 15 '18 at 16:19




Instead of simply stating "does not compile", it would be much better if you could show the precise error message you are getting. In particular, at least one answer is operating under the assumption that you are getting a syntax error (although in that case, "does not parse" would be more correct than "does not compile"), but I don't think a syntax error is the problem.
– Jörg W Mittag
Dec 15 '18 at 16:19












@JörgWMittag The compilation error prints incompatible types: bad return type in lambda expression missing return value. @Pshemo before I started this thread I checked what is the signature is. Consumer.accept(T t) should return void (docs.oracle.com/javase/8/docs/api/java/util/function/…)
– Leonid Dashko
Dec 15 '18 at 19:25






@JörgWMittag The compilation error prints incompatible types: bad return type in lambda expression missing return value. @Pshemo before I started this thread I checked what is the signature is. Consumer.accept(T t) should return void (docs.oracle.com/javase/8/docs/api/java/util/function/…)
– Leonid Dashko
Dec 15 '18 at 19:25






1




1




@LeonidDashko when I ran this on IntelliJ IDEA I got the error I've included in the post. However, since it's not word for word the same as what you've just mentioned, please consider updating the post with the exact information.
– Aomine
Dec 15 '18 at 20:07






@LeonidDashko when I ran this on IntelliJ IDEA I got the error I've included in the post. However, since it's not word for word the same as what you've just mentioned, please consider updating the post with the exact information.
– Aomine
Dec 15 '18 at 20:07














3 Answers
3






active

oldest

votes


















13














Though you might be looking just for



Stream.of(1,2,3).forEach(list::add); // adding all to `list`



why does the first example compile if List interface has following
signature boolean add(E e)




Primarily because the return type of the method is ignored in the first call. This is what it expands to:



Stream.of(1,2,3).forEach(new Consumer<Integer>() {
@Override
public void accept(Integer i) {
list.add(1); // ignored return type
}
}); // COMPILES


On the other hand, the other lambda representation is more like a Predicate(which is also a FunctionalInterface) represented as returning true always from its test method. If you even try to represent it as a Consumer, it might just look like



Stream.of(1,2,3).forEach(new Consumer<Integer>() {
@Override
public void accept(Integer i) {
return true; // you can correlate easily now why this wouldn't compile
}
}); // DOES NOT COMPILE!




To add to the design basis via a comment from Brian




Java allows you to call a method and ignore the return value (a method invocation expression as a statement). Since we allow this at
the invocation, we also allow this when adapting a method to a
functional interface whose arguments are compatible but the functional
interface is void-returning.




Edit: To put it in his own words as close to the language spec:




More precisely, list.add(x) is a statement expression, and
therefore is void-compatible. true is not a statement expression,
and therefore not void-compatible. forEach(Consumer) requires a
void-compatible lambda.







share|improve this answer



















  • 3




    More precisely, list.add(x) is a statement expression, and therefore is void-compatible. true is not a statement expression, and therefore not void-compatible. forEach(Consumer) requires a void-compatible lambda.
    – Brian Goetz
    Dec 16 '18 at 21:33



















2














forEach() as a Consumer as the one and only parameter therefore you need to give an implemention of the method accept() which returns void so on the second example you're implementing a method with the given assinature static boolean method(int).






share|improve this answer

















  • 6




    Can you explain, why list.add(1), an expression that evaluates to true is a correct implementation of a Consumer, whereas true, an expression that evaluates to true, is an incorrect implementation?
    – Jörg W Mittag
    Dec 15 '18 at 16:15






  • 2




    Like other people said before if you expand the lambda with the { } you'll get an expression on first case and an invalid statement at second.
    – chriptus13
    Dec 15 '18 at 16:59






  • 2




    As was pointed out in another answer, the reason is void-compatibility, not syntax.
    – Jörg W Mittag
    Dec 15 '18 at 17:33






  • 2




    If you don't use the brackets it either is a value which gets translated to a return or a method call.
    – chriptus13
    Dec 15 '18 at 17:34






  • 3




    @JörgWMittag: That’s the right question to ask. The answer is that a lambda body is void-compatible only if “the body of a lambda is a statement expression (that is, an expression that would be allowed to stand alone as a statement)” (§15.27.3), and in Java true; is not a valid statement (contrast other languages).
    – wchargin
    Dec 15 '18 at 20:09



















0














The Special Void-Compatibility Rule (JLS) says that a lambda that returns void may accept a statement whose return is non-void. In this case, the return is discarded. hence this compiles.



Stream.of(1,2,3).forEach(i -> list.add(1)); // return value of add is ignored


To word it a bit differently by quoting Java-8 in Action book:




If a lambda has a statement expression as its body, it’s compatible
with a function descriptor that returns void (provided the parameter
list is compatible too). For example, both of the following lines are
legal even though the method add of a List returns a boolean and not
void as expected in the Consumer context (T -> void):




// Predicate has a boolean return
Predicate<String> p = s -> list.add(s);
// Consumer has a void return
Consumer<String> b = s -> list.add(s);


As for the second example, this is explicitly trying to return a boolean where it's not expected hence not possible.



Stream.of(1,2,3).forEach(i -> true);  


in other words:



Stream.of(1,2,3).forEach(i -> {return true;});


As you already know forEach takes a Consumer so attempting to "explicitly" return a boolean should & will yield a compilation error.






share|improve this answer



















  • 1




    I believe that this is the answer, but I am still having trouble seeing it clearly. The lambda spec explicitly distinguishes between lambdas with expression bodies and lambdas with block bodies, whereas void-compatibility rule talks specifically about lambdas with a block body and does not mention expression-bodied lambdas. However, both examples in the question are expression-bodies lambdas. I cannot point my finger on exactly that part of the spec that says this. Your quote from Java in Action seems to interpret the spec the same way as you, and I believe that interpretation is correct, I …
    – Jörg W Mittag
    Dec 15 '18 at 17:37










  • … just can't find where it is actually supported by the spec.
    – Jörg W Mittag
    Dec 15 '18 at 17:37


















3 Answers
3






active

oldest

votes








3 Answers
3






active

oldest

votes









active

oldest

votes






active

oldest

votes









13














Though you might be looking just for



Stream.of(1,2,3).forEach(list::add); // adding all to `list`



why does the first example compile if List interface has following
signature boolean add(E e)




Primarily because the return type of the method is ignored in the first call. This is what it expands to:



Stream.of(1,2,3).forEach(new Consumer<Integer>() {
@Override
public void accept(Integer i) {
list.add(1); // ignored return type
}
}); // COMPILES


On the other hand, the other lambda representation is more like a Predicate(which is also a FunctionalInterface) represented as returning true always from its test method. If you even try to represent it as a Consumer, it might just look like



Stream.of(1,2,3).forEach(new Consumer<Integer>() {
@Override
public void accept(Integer i) {
return true; // you can correlate easily now why this wouldn't compile
}
}); // DOES NOT COMPILE!




To add to the design basis via a comment from Brian




Java allows you to call a method and ignore the return value (a method invocation expression as a statement). Since we allow this at
the invocation, we also allow this when adapting a method to a
functional interface whose arguments are compatible but the functional
interface is void-returning.




Edit: To put it in his own words as close to the language spec:




More precisely, list.add(x) is a statement expression, and
therefore is void-compatible. true is not a statement expression,
and therefore not void-compatible. forEach(Consumer) requires a
void-compatible lambda.







share|improve this answer



















  • 3




    More precisely, list.add(x) is a statement expression, and therefore is void-compatible. true is not a statement expression, and therefore not void-compatible. forEach(Consumer) requires a void-compatible lambda.
    – Brian Goetz
    Dec 16 '18 at 21:33
















13














Though you might be looking just for



Stream.of(1,2,3).forEach(list::add); // adding all to `list`



why does the first example compile if List interface has following
signature boolean add(E e)




Primarily because the return type of the method is ignored in the first call. This is what it expands to:



Stream.of(1,2,3).forEach(new Consumer<Integer>() {
@Override
public void accept(Integer i) {
list.add(1); // ignored return type
}
}); // COMPILES


On the other hand, the other lambda representation is more like a Predicate(which is also a FunctionalInterface) represented as returning true always from its test method. If you even try to represent it as a Consumer, it might just look like



Stream.of(1,2,3).forEach(new Consumer<Integer>() {
@Override
public void accept(Integer i) {
return true; // you can correlate easily now why this wouldn't compile
}
}); // DOES NOT COMPILE!




To add to the design basis via a comment from Brian




Java allows you to call a method and ignore the return value (a method invocation expression as a statement). Since we allow this at
the invocation, we also allow this when adapting a method to a
functional interface whose arguments are compatible but the functional
interface is void-returning.




Edit: To put it in his own words as close to the language spec:




More precisely, list.add(x) is a statement expression, and
therefore is void-compatible. true is not a statement expression,
and therefore not void-compatible. forEach(Consumer) requires a
void-compatible lambda.







share|improve this answer



















  • 3




    More precisely, list.add(x) is a statement expression, and therefore is void-compatible. true is not a statement expression, and therefore not void-compatible. forEach(Consumer) requires a void-compatible lambda.
    – Brian Goetz
    Dec 16 '18 at 21:33














13












13








13






Though you might be looking just for



Stream.of(1,2,3).forEach(list::add); // adding all to `list`



why does the first example compile if List interface has following
signature boolean add(E e)




Primarily because the return type of the method is ignored in the first call. This is what it expands to:



Stream.of(1,2,3).forEach(new Consumer<Integer>() {
@Override
public void accept(Integer i) {
list.add(1); // ignored return type
}
}); // COMPILES


On the other hand, the other lambda representation is more like a Predicate(which is also a FunctionalInterface) represented as returning true always from its test method. If you even try to represent it as a Consumer, it might just look like



Stream.of(1,2,3).forEach(new Consumer<Integer>() {
@Override
public void accept(Integer i) {
return true; // you can correlate easily now why this wouldn't compile
}
}); // DOES NOT COMPILE!




To add to the design basis via a comment from Brian




Java allows you to call a method and ignore the return value (a method invocation expression as a statement). Since we allow this at
the invocation, we also allow this when adapting a method to a
functional interface whose arguments are compatible but the functional
interface is void-returning.




Edit: To put it in his own words as close to the language spec:




More precisely, list.add(x) is a statement expression, and
therefore is void-compatible. true is not a statement expression,
and therefore not void-compatible. forEach(Consumer) requires a
void-compatible lambda.







share|improve this answer














Though you might be looking just for



Stream.of(1,2,3).forEach(list::add); // adding all to `list`



why does the first example compile if List interface has following
signature boolean add(E e)




Primarily because the return type of the method is ignored in the first call. This is what it expands to:



Stream.of(1,2,3).forEach(new Consumer<Integer>() {
@Override
public void accept(Integer i) {
list.add(1); // ignored return type
}
}); // COMPILES


On the other hand, the other lambda representation is more like a Predicate(which is also a FunctionalInterface) represented as returning true always from its test method. If you even try to represent it as a Consumer, it might just look like



Stream.of(1,2,3).forEach(new Consumer<Integer>() {
@Override
public void accept(Integer i) {
return true; // you can correlate easily now why this wouldn't compile
}
}); // DOES NOT COMPILE!




To add to the design basis via a comment from Brian




Java allows you to call a method and ignore the return value (a method invocation expression as a statement). Since we allow this at
the invocation, we also allow this when adapting a method to a
functional interface whose arguments are compatible but the functional
interface is void-returning.




Edit: To put it in his own words as close to the language spec:




More precisely, list.add(x) is a statement expression, and
therefore is void-compatible. true is not a statement expression,
and therefore not void-compatible. forEach(Consumer) requires a
void-compatible lambda.








share|improve this answer














share|improve this answer



share|improve this answer








edited Dec 17 '18 at 1:21

























answered Dec 15 '18 at 16:21









nullpointernullpointer

44.4k1095183




44.4k1095183








  • 3




    More precisely, list.add(x) is a statement expression, and therefore is void-compatible. true is not a statement expression, and therefore not void-compatible. forEach(Consumer) requires a void-compatible lambda.
    – Brian Goetz
    Dec 16 '18 at 21:33














  • 3




    More precisely, list.add(x) is a statement expression, and therefore is void-compatible. true is not a statement expression, and therefore not void-compatible. forEach(Consumer) requires a void-compatible lambda.
    – Brian Goetz
    Dec 16 '18 at 21:33








3




3




More precisely, list.add(x) is a statement expression, and therefore is void-compatible. true is not a statement expression, and therefore not void-compatible. forEach(Consumer) requires a void-compatible lambda.
– Brian Goetz
Dec 16 '18 at 21:33




More precisely, list.add(x) is a statement expression, and therefore is void-compatible. true is not a statement expression, and therefore not void-compatible. forEach(Consumer) requires a void-compatible lambda.
– Brian Goetz
Dec 16 '18 at 21:33













2














forEach() as a Consumer as the one and only parameter therefore you need to give an implemention of the method accept() which returns void so on the second example you're implementing a method with the given assinature static boolean method(int).






share|improve this answer

















  • 6




    Can you explain, why list.add(1), an expression that evaluates to true is a correct implementation of a Consumer, whereas true, an expression that evaluates to true, is an incorrect implementation?
    – Jörg W Mittag
    Dec 15 '18 at 16:15






  • 2




    Like other people said before if you expand the lambda with the { } you'll get an expression on first case and an invalid statement at second.
    – chriptus13
    Dec 15 '18 at 16:59






  • 2




    As was pointed out in another answer, the reason is void-compatibility, not syntax.
    – Jörg W Mittag
    Dec 15 '18 at 17:33






  • 2




    If you don't use the brackets it either is a value which gets translated to a return or a method call.
    – chriptus13
    Dec 15 '18 at 17:34






  • 3




    @JörgWMittag: That’s the right question to ask. The answer is that a lambda body is void-compatible only if “the body of a lambda is a statement expression (that is, an expression that would be allowed to stand alone as a statement)” (§15.27.3), and in Java true; is not a valid statement (contrast other languages).
    – wchargin
    Dec 15 '18 at 20:09
















2














forEach() as a Consumer as the one and only parameter therefore you need to give an implemention of the method accept() which returns void so on the second example you're implementing a method with the given assinature static boolean method(int).






share|improve this answer

















  • 6




    Can you explain, why list.add(1), an expression that evaluates to true is a correct implementation of a Consumer, whereas true, an expression that evaluates to true, is an incorrect implementation?
    – Jörg W Mittag
    Dec 15 '18 at 16:15






  • 2




    Like other people said before if you expand the lambda with the { } you'll get an expression on first case and an invalid statement at second.
    – chriptus13
    Dec 15 '18 at 16:59






  • 2




    As was pointed out in another answer, the reason is void-compatibility, not syntax.
    – Jörg W Mittag
    Dec 15 '18 at 17:33






  • 2




    If you don't use the brackets it either is a value which gets translated to a return or a method call.
    – chriptus13
    Dec 15 '18 at 17:34






  • 3




    @JörgWMittag: That’s the right question to ask. The answer is that a lambda body is void-compatible only if “the body of a lambda is a statement expression (that is, an expression that would be allowed to stand alone as a statement)” (§15.27.3), and in Java true; is not a valid statement (contrast other languages).
    – wchargin
    Dec 15 '18 at 20:09














2












2








2






forEach() as a Consumer as the one and only parameter therefore you need to give an implemention of the method accept() which returns void so on the second example you're implementing a method with the given assinature static boolean method(int).






share|improve this answer












forEach() as a Consumer as the one and only parameter therefore you need to give an implemention of the method accept() which returns void so on the second example you're implementing a method with the given assinature static boolean method(int).







share|improve this answer












share|improve this answer



share|improve this answer










answered Dec 15 '18 at 16:09









chriptus13chriptus13

381212




381212








  • 6




    Can you explain, why list.add(1), an expression that evaluates to true is a correct implementation of a Consumer, whereas true, an expression that evaluates to true, is an incorrect implementation?
    – Jörg W Mittag
    Dec 15 '18 at 16:15






  • 2




    Like other people said before if you expand the lambda with the { } you'll get an expression on first case and an invalid statement at second.
    – chriptus13
    Dec 15 '18 at 16:59






  • 2




    As was pointed out in another answer, the reason is void-compatibility, not syntax.
    – Jörg W Mittag
    Dec 15 '18 at 17:33






  • 2




    If you don't use the brackets it either is a value which gets translated to a return or a method call.
    – chriptus13
    Dec 15 '18 at 17:34






  • 3




    @JörgWMittag: That’s the right question to ask. The answer is that a lambda body is void-compatible only if “the body of a lambda is a statement expression (that is, an expression that would be allowed to stand alone as a statement)” (§15.27.3), and in Java true; is not a valid statement (contrast other languages).
    – wchargin
    Dec 15 '18 at 20:09














  • 6




    Can you explain, why list.add(1), an expression that evaluates to true is a correct implementation of a Consumer, whereas true, an expression that evaluates to true, is an incorrect implementation?
    – Jörg W Mittag
    Dec 15 '18 at 16:15






  • 2




    Like other people said before if you expand the lambda with the { } you'll get an expression on first case and an invalid statement at second.
    – chriptus13
    Dec 15 '18 at 16:59






  • 2




    As was pointed out in another answer, the reason is void-compatibility, not syntax.
    – Jörg W Mittag
    Dec 15 '18 at 17:33






  • 2




    If you don't use the brackets it either is a value which gets translated to a return or a method call.
    – chriptus13
    Dec 15 '18 at 17:34






  • 3




    @JörgWMittag: That’s the right question to ask. The answer is that a lambda body is void-compatible only if “the body of a lambda is a statement expression (that is, an expression that would be allowed to stand alone as a statement)” (§15.27.3), and in Java true; is not a valid statement (contrast other languages).
    – wchargin
    Dec 15 '18 at 20:09








6




6




Can you explain, why list.add(1), an expression that evaluates to true is a correct implementation of a Consumer, whereas true, an expression that evaluates to true, is an incorrect implementation?
– Jörg W Mittag
Dec 15 '18 at 16:15




Can you explain, why list.add(1), an expression that evaluates to true is a correct implementation of a Consumer, whereas true, an expression that evaluates to true, is an incorrect implementation?
– Jörg W Mittag
Dec 15 '18 at 16:15




2




2




Like other people said before if you expand the lambda with the { } you'll get an expression on first case and an invalid statement at second.
– chriptus13
Dec 15 '18 at 16:59




Like other people said before if you expand the lambda with the { } you'll get an expression on first case and an invalid statement at second.
– chriptus13
Dec 15 '18 at 16:59




2




2




As was pointed out in another answer, the reason is void-compatibility, not syntax.
– Jörg W Mittag
Dec 15 '18 at 17:33




As was pointed out in another answer, the reason is void-compatibility, not syntax.
– Jörg W Mittag
Dec 15 '18 at 17:33




2




2




If you don't use the brackets it either is a value which gets translated to a return or a method call.
– chriptus13
Dec 15 '18 at 17:34




If you don't use the brackets it either is a value which gets translated to a return or a method call.
– chriptus13
Dec 15 '18 at 17:34




3




3




@JörgWMittag: That’s the right question to ask. The answer is that a lambda body is void-compatible only if “the body of a lambda is a statement expression (that is, an expression that would be allowed to stand alone as a statement)” (§15.27.3), and in Java true; is not a valid statement (contrast other languages).
– wchargin
Dec 15 '18 at 20:09




@JörgWMittag: That’s the right question to ask. The answer is that a lambda body is void-compatible only if “the body of a lambda is a statement expression (that is, an expression that would be allowed to stand alone as a statement)” (§15.27.3), and in Java true; is not a valid statement (contrast other languages).
– wchargin
Dec 15 '18 at 20:09











0














The Special Void-Compatibility Rule (JLS) says that a lambda that returns void may accept a statement whose return is non-void. In this case, the return is discarded. hence this compiles.



Stream.of(1,2,3).forEach(i -> list.add(1)); // return value of add is ignored


To word it a bit differently by quoting Java-8 in Action book:




If a lambda has a statement expression as its body, it’s compatible
with a function descriptor that returns void (provided the parameter
list is compatible too). For example, both of the following lines are
legal even though the method add of a List returns a boolean and not
void as expected in the Consumer context (T -> void):




// Predicate has a boolean return
Predicate<String> p = s -> list.add(s);
// Consumer has a void return
Consumer<String> b = s -> list.add(s);


As for the second example, this is explicitly trying to return a boolean where it's not expected hence not possible.



Stream.of(1,2,3).forEach(i -> true);  


in other words:



Stream.of(1,2,3).forEach(i -> {return true;});


As you already know forEach takes a Consumer so attempting to "explicitly" return a boolean should & will yield a compilation error.






share|improve this answer



















  • 1




    I believe that this is the answer, but I am still having trouble seeing it clearly. The lambda spec explicitly distinguishes between lambdas with expression bodies and lambdas with block bodies, whereas void-compatibility rule talks specifically about lambdas with a block body and does not mention expression-bodied lambdas. However, both examples in the question are expression-bodies lambdas. I cannot point my finger on exactly that part of the spec that says this. Your quote from Java in Action seems to interpret the spec the same way as you, and I believe that interpretation is correct, I …
    – Jörg W Mittag
    Dec 15 '18 at 17:37










  • … just can't find where it is actually supported by the spec.
    – Jörg W Mittag
    Dec 15 '18 at 17:37
















0














The Special Void-Compatibility Rule (JLS) says that a lambda that returns void may accept a statement whose return is non-void. In this case, the return is discarded. hence this compiles.



Stream.of(1,2,3).forEach(i -> list.add(1)); // return value of add is ignored


To word it a bit differently by quoting Java-8 in Action book:




If a lambda has a statement expression as its body, it’s compatible
with a function descriptor that returns void (provided the parameter
list is compatible too). For example, both of the following lines are
legal even though the method add of a List returns a boolean and not
void as expected in the Consumer context (T -> void):




// Predicate has a boolean return
Predicate<String> p = s -> list.add(s);
// Consumer has a void return
Consumer<String> b = s -> list.add(s);


As for the second example, this is explicitly trying to return a boolean where it's not expected hence not possible.



Stream.of(1,2,3).forEach(i -> true);  


in other words:



Stream.of(1,2,3).forEach(i -> {return true;});


As you already know forEach takes a Consumer so attempting to "explicitly" return a boolean should & will yield a compilation error.






share|improve this answer



















  • 1




    I believe that this is the answer, but I am still having trouble seeing it clearly. The lambda spec explicitly distinguishes between lambdas with expression bodies and lambdas with block bodies, whereas void-compatibility rule talks specifically about lambdas with a block body and does not mention expression-bodied lambdas. However, both examples in the question are expression-bodies lambdas. I cannot point my finger on exactly that part of the spec that says this. Your quote from Java in Action seems to interpret the spec the same way as you, and I believe that interpretation is correct, I …
    – Jörg W Mittag
    Dec 15 '18 at 17:37










  • … just can't find where it is actually supported by the spec.
    – Jörg W Mittag
    Dec 15 '18 at 17:37














0












0








0






The Special Void-Compatibility Rule (JLS) says that a lambda that returns void may accept a statement whose return is non-void. In this case, the return is discarded. hence this compiles.



Stream.of(1,2,3).forEach(i -> list.add(1)); // return value of add is ignored


To word it a bit differently by quoting Java-8 in Action book:




If a lambda has a statement expression as its body, it’s compatible
with a function descriptor that returns void (provided the parameter
list is compatible too). For example, both of the following lines are
legal even though the method add of a List returns a boolean and not
void as expected in the Consumer context (T -> void):




// Predicate has a boolean return
Predicate<String> p = s -> list.add(s);
// Consumer has a void return
Consumer<String> b = s -> list.add(s);


As for the second example, this is explicitly trying to return a boolean where it's not expected hence not possible.



Stream.of(1,2,3).forEach(i -> true);  


in other words:



Stream.of(1,2,3).forEach(i -> {return true;});


As you already know forEach takes a Consumer so attempting to "explicitly" return a boolean should & will yield a compilation error.






share|improve this answer














The Special Void-Compatibility Rule (JLS) says that a lambda that returns void may accept a statement whose return is non-void. In this case, the return is discarded. hence this compiles.



Stream.of(1,2,3).forEach(i -> list.add(1)); // return value of add is ignored


To word it a bit differently by quoting Java-8 in Action book:




If a lambda has a statement expression as its body, it’s compatible
with a function descriptor that returns void (provided the parameter
list is compatible too). For example, both of the following lines are
legal even though the method add of a List returns a boolean and not
void as expected in the Consumer context (T -> void):




// Predicate has a boolean return
Predicate<String> p = s -> list.add(s);
// Consumer has a void return
Consumer<String> b = s -> list.add(s);


As for the second example, this is explicitly trying to return a boolean where it's not expected hence not possible.



Stream.of(1,2,3).forEach(i -> true);  


in other words:



Stream.of(1,2,3).forEach(i -> {return true;});


As you already know forEach takes a Consumer so attempting to "explicitly" return a boolean should & will yield a compilation error.







share|improve this answer














share|improve this answer



share|improve this answer








edited Dec 15 '18 at 17:34

























answered Dec 15 '18 at 16:29









AomineAomine

41.6k74071




41.6k74071








  • 1




    I believe that this is the answer, but I am still having trouble seeing it clearly. The lambda spec explicitly distinguishes between lambdas with expression bodies and lambdas with block bodies, whereas void-compatibility rule talks specifically about lambdas with a block body and does not mention expression-bodied lambdas. However, both examples in the question are expression-bodies lambdas. I cannot point my finger on exactly that part of the spec that says this. Your quote from Java in Action seems to interpret the spec the same way as you, and I believe that interpretation is correct, I …
    – Jörg W Mittag
    Dec 15 '18 at 17:37










  • … just can't find where it is actually supported by the spec.
    – Jörg W Mittag
    Dec 15 '18 at 17:37














  • 1




    I believe that this is the answer, but I am still having trouble seeing it clearly. The lambda spec explicitly distinguishes between lambdas with expression bodies and lambdas with block bodies, whereas void-compatibility rule talks specifically about lambdas with a block body and does not mention expression-bodied lambdas. However, both examples in the question are expression-bodies lambdas. I cannot point my finger on exactly that part of the spec that says this. Your quote from Java in Action seems to interpret the spec the same way as you, and I believe that interpretation is correct, I …
    – Jörg W Mittag
    Dec 15 '18 at 17:37










  • … just can't find where it is actually supported by the spec.
    – Jörg W Mittag
    Dec 15 '18 at 17:37








1




1




I believe that this is the answer, but I am still having trouble seeing it clearly. The lambda spec explicitly distinguishes between lambdas with expression bodies and lambdas with block bodies, whereas void-compatibility rule talks specifically about lambdas with a block body and does not mention expression-bodied lambdas. However, both examples in the question are expression-bodies lambdas. I cannot point my finger on exactly that part of the spec that says this. Your quote from Java in Action seems to interpret the spec the same way as you, and I believe that interpretation is correct, I …
– Jörg W Mittag
Dec 15 '18 at 17:37




I believe that this is the answer, but I am still having trouble seeing it clearly. The lambda spec explicitly distinguishes between lambdas with expression bodies and lambdas with block bodies, whereas void-compatibility rule talks specifically about lambdas with a block body and does not mention expression-bodied lambdas. However, both examples in the question are expression-bodies lambdas. I cannot point my finger on exactly that part of the spec that says this. Your quote from Java in Action seems to interpret the spec the same way as you, and I believe that interpretation is correct, I …
– Jörg W Mittag
Dec 15 '18 at 17:37












… just can't find where it is actually supported by the spec.
– Jörg W Mittag
Dec 15 '18 at 17:37




… just can't find where it is actually supported by the spec.
– Jörg W Mittag
Dec 15 '18 at 17:37



Popular posts from this blog

Plaza Victoria

Puebla de Zaragoza

Musa