Win a copy of Zero to AI - A non-technical, hype-free guide to prospering in the AI era this week in the Artificial Intelligence and Machine Learning forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Liutauras Vilda
  • Paul Clapham
  • Bear Bibeault
  • Jeanne Boyarsky
Sheriffs:
  • Ron McLeod
  • Tim Cooke
  • Devaka Cooray
Saloon Keepers:
  • Tim Moores
  • Tim Holloway
  • Jj Roberts
  • Stephan van Hulst
  • Carey Brown
Bartenders:
  • salvin francis
  • Scott Selikoff
  • fred rosenberger

What Are "void-compatible" Blocks And "value-compatible" Blocks

 
Ranch Foreman
Posts: 122
12
Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I ask this question because I'm reading the book "Modern Java in Action", which has the following definition of "void-compatible":

Modern Java in Action §3.5.2 wrote:SPECIAL VOID-COMPATIBILITY RULE

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):


This part is easy to understand. For your convenience, here is the definition of statement expression.



But JLS §15.27.2 has a very different definition of "void-compatible" together with "value-compatible".

JLS §15.27.2 wrote:A block lambda body is void-compatible if every return statement in the block has the form return;.

A block lambda body is value-compatible if it cannot complete normally (§14.21) and every return statement in the block has the form return Expression;.

It is a compile-time error if a block lambda body is neither void-compatible nor value-compatible.

In a value-compatible block lambda body, the result expressions are any expressions that may produce an invocation's value. Specifically, for each statement of the form return Expression ; contained by the body, the Expression is a result expression.


The following lambda bodies are void-compatible:

These are value-compatible:

These are both:

This is neither:



And according to JLS §15.12.2.1, these are used to decide if a lambda expression is potentially compatible with a functional interface type.

JLS §15.12.2.1 wrote:A lambda expression (§15.27) is potentially compatible with a functional interface type T (§9.8) if all of the following are true:

- The arity of the function type of T (§9.9) is the same as the arity of the lambda expression.

- If the function type of T has a void return, then the lambda body is either a statement expression (§14.8) or a void-compatible block (§15.27.2).

- If the function type of T has a (non-void) return type, then the lambda body is either an expression or a value-compatible block (§15.27.2).




Hope someone could help me with some details and examples that what are "void-compatible" blocks and "value-compatible" blocks and how they are used in deciding functional interface type compatibility.
 
Author
Posts: 192
9
Scala IntelliJ IDE Netbeans IDE Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Not sure if I'll answer the question you actually asked, or just the one I think you're asking, but let me try:

If you have, for example, a Consumer, the expected return of the lambda is void, but as you've noted, returning something implicitly is actually OK in this situation, just like calling:

as a statement is OK, even though it's technically an expression. That's "void compatible". But, if you return something explicitly, that's not void compatible.

So, these work as "void compatible" even though the expressions in them appear to return values:


But these are not void compatible, because the expressions that they return are not in acceptable forms:


Quite separately, a lambda that returns something is value compatible (which does not prevent it being void compatible too, as above). A lambda for which the type is determined to such that a returned value is expected must be value compatible to have a chance of compiling (and of course the types must match, and so must the argument lists).

However, it's conceptually possible to create a lambda looking thing that's neither one thing nor the other, this would be the situation with the example you gave. These both fail, that is, the lambda doesn't work for either returning a value, or for being void compatible:



I think the point is simply to give the same flexibility to lambdas as exists for statements made of expressions that are being used for their side-effects i.e. the situation you already called out:



Does this help?
Cheers,
Simon
 
Frank Mi
Ranch Foreman
Posts: 122
12
Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks, Simon! Your answer is really helpful, very clear and easy to understand!

I think my biggest problem here is that, I don't understand the definition and examples shown in JLS. For example, how does the sentence "A block lambda body is void-compatible if every return statement in the block has the form return;" relate to its examples? Would you mind explaining the definition of "void-compatible" and "value-compatible" described in JLS with their examples? They are in the middle part of my original post.
 
Simon Roberts
Author
Posts: 192
9
Scala IntelliJ IDE Netbeans IDE Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Oh, if the code in a block lambda simply ends with return-semicolon (i.e. exactly return; ) then it's explicitly a void return, right? Just like if you have a function



Void compatible simply means you'll be able to use it--that is, it will compile OK if used--in a context where the lambda needed is implementing a method that returns void. That, as you've seen, includes some method bodies that actually do appear to return values, but not if they do so explicitly.

Value compatible means the lambda body does return a value.

A lambda's body can be both--that just means it returns a value, but in a way that's OK to ignore.  So, in my examples, the lambdas that were Consumer or Runnable implement methods that return void. But it's possible to do it with some types of lambda body that do return something. Take another look at  the bodies of those lambda examples, I also tried to be a bit more explicit in the preamble to the pairs of examples.

Any better?
 
Frank Mi
Ranch Foreman
Posts: 122
12
Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes, much better. Just one last question. In this sentence, "A block lambda body is value-compatible if it cannot complete normally and every return statement in the block has the form return Expression;." What does it mean by cannot complete normally? I feel the examples complete pretty well.
 
Simon Roberts
Author
Posts: 192
9
Scala IntelliJ IDE Netbeans IDE Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
... deleted, more to think about ...
 
Saloon Keeper
Posts: 12419
269
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Simon Roberts wrote:Completing normally means regular return


This is not correct I'm afraid. Normal completion is when a method runs to the end without encountering any keyword that will cause it to return prematurely. This includes the 'return' keyword.

If a block could in any way complete normally, it wouldn't be value-compatible; every execution of a value compatible block needs to either return a value or throw an exception.

The following block is not value-compatible:

The reason is that if the condition in the if-statement is false, the block will complete normally (i.e. without return statement).
 
Marshal
Posts: 70625
288
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Frank Mi wrote:. . .
The following lambda bodies are void-compatible:
. . .
These are value-compatible:
. . .
These are both:. . . .

Please explain more about why you said, “both”; I think you are correct, however.
 
Stephan van Hulst
Saloon Keeper
Posts: 12419
269
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It's an example from the JLS that Frank quoted.

The examples are void-compatible because all return statements are of the form "return;". This is trivially true because there are no return statements.

The examples are value-compatible because they can't complete normally (the only way for execution to return is through an exception) AND all return statements are of the form "return Expression;". This is trivially true because there are no return statements.
 
Simon Roberts
Author
Posts: 192
9
Scala IntelliJ IDE Netbeans IDE Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Stephan van Hulst wrote: ... Normal completion is when a method runs to the end without encountering any keyword that will cause it to return prematurely. This includes the 'return' keyword.



Good catch, I didn't pay enough attention to the lambda-related descriptions of this. Let me try to be both precise and helpful, let's see how this goes

First, in my "defense", Java has (at least) two different definitions of "Normal and Abrupt Completion"

One relates to statements, and is in JLS 14.1. It seems to boil down to "normal is anything except acting on: break, continue, return, throw. This seems to be the one that is referred to in the pieces that Frank was asking about, since it describes the execution of a method's body.

The second definition relates to evaluation (which includes expressions, and thereby the invocation of a method call), and is in JLS 15.6. This one (which is what I was thinking of) says:

If all the steps are carried out without an exception being thrown, the expression is said to complete normally



Now, in the situation Frank was asking about in that follow-up question the point is that if a method's execution "completes normally" (governed by JLS 14.1) that means in effect that it "ran off the end of the method body". And if it runs off the end of the method body, it cannot have executed a return xxx statement (indeed it cannot have executed any return statement, whether with or without a value). But, to be "value compatible, all return statements must return a (compatible with the declared return type) return statement. Hence, anything that completes normally in this sense cannot be "value compatible".

As a teacher, I am again reminded of the huge distinction between specification and explanation!

Anyway, Stephan, perhaps you'd like to comment on/confirm/deny my expansion there?
Cheers,
Simon


 
Stephan van Hulst
Saloon Keeper
Posts: 12419
269
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You're correct, but while we're on the topic of specification versus explanation, I'd like to argue that as far as explanation goes, it's easier to treat the concept of abrupt/normal completion the same for expressions and statements.

The difference between the two follows naturally from not being able to use break/continue/return/throw in an expression. Making the distinction explicit is not necessary.
 
Simon Roberts
Author
Posts: 192
9
Scala IntelliJ IDE Netbeans IDE Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well, I'm inclined to disagree there. For two reasons:

1. the spec calls out two distinct situations, and gives them different (and not equivalent, see point 2) descriptions.

2. the situation we've just encountered shows the difference. The execution of a body of a method that has a return statement does not "complete normally", and yet, that same method's invocation does complete normally ;)

 
Frank Mi
Ranch Foreman
Posts: 122
12
Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stephan and Simon indeed agree on the same idea that "return" does NOT "complete normally". And this point exactly solved my last question, because I don't know that! Thank you all!

From the way you guys pointed out, I found there is a concise statement in JLS: JLS §14.17 The return Statement:

JLS §14.17 The return Statement wrote:It can be seen, then, that a return statement always completes abruptly.




 
Stephan van Hulst
Saloon Keeper
Posts: 12419
269
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Simon Roberts wrote:The execution of a body of a method that has a return statement does not "complete normally", and yet, that same method's invocation does complete normally ;)


The difference is forced because you substitute "method definition" for "method invocation". There are plenty of places in Java where you can't legally substitute a definition for an invocation, and the reason is not because there are separate definitions for "normal completion".
 
Stephan van Hulst
Saloon Keeper
Posts: 12419
269
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Frank Mi wrote:Stephan and Simon indeed agree on the same idea that "return" does NOT "complete normally"


We do agree. We just went on a sidetrack.
 
Frank Mi
Ranch Foreman
Posts: 122
12
Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:We do agree. We just went on a sidetrack.


What is the sidetrack? I didn't get it. Maybe I would like to join the discussion.  
 
Simon Roberts
Author
Posts: 192
9
Scala IntelliJ IDE Netbeans IDE Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Frank Mi wrote:...
What is the sidetrack? I didn't get it. Maybe I would like to join the discussion.  



Perspective (and to an extent perhaps terminology) We do indeed agree on the facts, now that Stephan corrected me. Very useful discussion; I love the smell of fresh new learning in the morning!
 
Frank Mi
Ranch Foreman
Posts: 122
12
Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I also learned a lot from both of you! Thanks!
 
Campbell Ritchie
Marshal
Posts: 70625
288
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Frank Mi wrote:Stephan and Simon indeed agree on the same idea that "return" does NOT "complete normally"

What's this? I go away for a few hours and come back to find people were discussing what complete normally means.
 
Frank Mi
Ranch Foreman
Posts: 122
12
Eclipse IDE Java Windows
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:

Frank Mi wrote:Stephan and Simon indeed agree on the same idea that "return" does NOT "complete normally"

What's this? I go away for a few hours and come back to find people were discussing what complete normally means.



They are completely normal, however I was not. Please ignore me.  
 
I didn't say it. I'm just telling you what this tiny ad said.
Thread Boost feature
https://coderanch.com/t/674455/Thread-Boost-feature
reply
    Bookmark Topic Watch Topic
  • New Topic