• 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 Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Devaka Cooray
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Jeanne Boyarsky
  • Tim Cooke
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Tim Moores
  • Mikalai Zaikin
  • Carey Brown
Bartenders:

why does the compiler complain about this ternary operator: "not a statement"?

 
Ranch Foreman
Posts: 226
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Trying to prepare for coding interviews. I don't know why the compiler complains about the ternary operator: "not a statement".


I understand I can convert it into an if-else statement.




 
Marshal
Posts: 8831
631
Mac OS X VI Editor BSD Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Anil Philip wrote:I don't know why the compiler complains about the ternary operator: "not a statement".


Well, the problem is not a ternary operator, but rather an expression not being a statement (expression itself is fine though). It has to be a statement at that point in your code.

So you have to do something with it in order to have a statement, eg.:
or

Expression on its own is not a statement. There are kind of expressions that also can be used as statements if they are followed by semicolon, and I had to look it up in JLS to see how they are officially called, so it is expression statement, eg.:
So that ^ can stay as a loose line.
 
Anil Philip
Ranch Foreman
Posts: 226
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank you for your reply.
How would I do it as part of the lambda in the stream?




 
Marshal
Posts: 4400
567
VSCode Eclipse IDE TypeScript Redhat MicroProfile Quarkus Java Linux
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Your example will not compile because forEach expects to operate on a Consumer, and a Consumer cannot return a value.

If you wrapped it with something like System.out.println like Liutauras showed before it will also fail to compile because variables in a lambda expression need to be effectively final, and positives, zeroes, and negatives are not.
Staff note (Ron McLeod) :

See Campbell's reply below for some clarifications.

 
Liutauras Vilda
Marshal
Posts: 8831
631
Mac OS X VI Editor BSD Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Anil Philip wrote:How would I do it as part of the lambda in the stream?


Most likely there are many ways to do it, you never said what though. But with a bit of guessing and trying to keep close to what you have, here is a way which first came to my mind:

I'm sure there are way more elegant ways of achieving the same.
 
Liutauras Vilda
Marshal
Posts: 8831
631
Mac OS X VI Editor BSD Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Here is perhaps slightly less verbose approach:

I've omitted other parts that are in the earlier post.
 
Marshal
Posts: 78698
374
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Please try not to quote the whole of the preceding post; that doesn't add anything new and the copied text is liable to removal.

Ron McLeod wrote:. . . variables in a lambda expression need to be effectively final . . .

Well, fields are allowed to change, but not parameters and local variables. You probably wouldn't want those three variables to be fields. You could create a local class to do the counting, and that will compile. But if a local class isn't overkill, I don't know what is!
I think that sort of counting is something Streams were not really designed for.
What you could do, however, is to create a Stream<Integer> with the boxed() method.
You can use groupingBy(). For the left argument, use something like Integer#signum(). For the right argument, try another Collector, maybe the one you can get here to do the counting. Note: You might end up with longs for your counts rather than ints. Have a look at Stephans's example here, but that is a rather more complicated situation than yours.
I got it to work on JShell, eventually.
 
Campbell Ritchie
Marshal
Posts: 78698
374
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

A few minutes ago, I wrote:. . . You can use groupingBy(). . . .

You use that to get a Collector which you pass to the Stream#collect() method. I lost that part when editing my post.
 
Anil Philip
Ranch Foreman
Posts: 226
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Ron McLeod wrote:Your example will not compile because forEach expects to operate on a Consumer, and a Consumer cannot return a value.

If you wrapped it with something like System.out.println like Liutauras showed before it will also fail to compile because variables in a lambda expression need to be effectively final, and positives, zeroes, and negatives are not.



In the code sample, they are static instance variables. Here is the full code I wrote. The question is from hacker rank.
Given an array of integers, calculate the ratios of its elements that are positive, negative, and zero. Print the decimal value of each fraction on a new line with  places after the decimal.


 
Campbell Ritchie
Marshal
Posts: 78698
374
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Anil Philip wrote:. . . static instance variables. . . .

Fields can be either static type or instance type (sometimes called non‑static), but not both. Those are static fields. Didn't HackerRank tell you that static variables are usually a bad idea?
There are quite a lot of things I don't like about that code.
  • Calling a List arr.
  • Reading from the keyboard would be much easier with a Scanner object.
  • Use of the float datatype for counting. Use of the float datatype for anything Use integer datatypes for counting.
  • Making everything static, except in functional programming. This code isn't functional.
  •  
    Campbell Ritchie
    Marshal
    Posts: 78698
    374
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    The HackerRank link says to calculate the proportions, which you can do with something like 1.0 * positives / total. The 1.0 * part converts the numbers to doubles.
     
    Anil Philip
    Ranch Foreman
    Posts: 226
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Campbell Ritchie wrote:

    Anil Philip wrote:. . . static instance variables. . . .

    Fields can be either static type or instance type (sometimes called non‑static), but not both. Those are static fields. Didn't HackerRank tell you that static variables are usually a bad idea?


    oops, I meant static member variables.
    To access them from the lambda and also update them, they have to be member variables (instance or class).
    Also, we are required to fill in only the plusMinus() method - nothing else. The reading input is provided by them.
     
    Liutauras Vilda
    Marshal
    Posts: 8831
    631
    Mac OS X VI Editor BSD Java
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Anil Philip wrote:In the code sample, they are static instance variables.


    I registered to that platform and I couldn't find them. You are asked to implement plusMinus() function that returns nothing, it should just print result as requested. I've passed the tests with my almost original code. I didn't know about ratios.
     
    Anil Philip
    Ranch Foreman
    Posts: 226
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Liutauras Vilda wrote:

    Anil Philip wrote:In the code sample, they are static instance variables.


    I registered to that platform and I couldn't find them. You are asked to implement plusMinus() function that returns nothing, it should just print result as requested. I've passed the tests with my almost original code. I didn't know about ratios.


    Are you able to see Plus Minus in the challenge over here. 1 week interview prep kit?
    My code works when I use the equivalent if-else (see commented out portion of code in my last post) instead of the expression.
    But they have something called "hidden tests" that have to be unlocked, no idea what they are (probably pay them some money - buy them some "pie" ), and it did not pass them all.


     
    Anil Philip
    Ranch Foreman
    Posts: 226
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Campbell Ritchie wrote:The HackerRank link says to calculate the proportions, which you can do with something like 1.0 * positives / total. The 1.0 * part converts the numbers to doubles.


    But if you start with a float, it is done automatically.
     
    Saloon Keeper
    Posts: 10555
    83
    Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
    • Likes 1
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    @Anil,

    You made "positives" (etc) float in order to have a floating point result from the divide. (Almost) Never use "float", use "double" instead it is the internal floating point default type and is more efficient. "float" should only be used when interfacing with legacy code.

    Additionally,  making those three variables float incurs some overhead for every increment (++) operation, change them to long. Then change  "n" to "double". Now the results of the divisions  will be floating point without the increment penalty.
     
    Marshal
    Posts: 28009
    94
    Eclipse IDE Firefox Browser MySQL Database
    • Likes 2
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    I decided to see if you could use a method reference to rehabilitate your code. And yes, you can. Here's my revised version:Note the unnecessary "whatever" variable there, it is actually necessary to allow the code to compile, for the reasons already discussed. You'll get a warning from the compiler, though. But at least it works in this context and it's a minimal change from your original try. And besides, method references are pure functional programming.

    As you see, even static methods can be used as the target of a method reference. (I assumed that your class was named "Test".) That's a bit in bad taste, though, it's generally recommended to eschew static methods as much as possible.
     
    Carey Brown
    Saloon Keeper
    Posts: 10555
    83
    Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    There's nothing in Hackerrank that requires that streams or lambdas be used.
     
    Anil Philip
    Ranch Foreman
    Posts: 226
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Carey Brown wrote:@Anil,

    You made "positives" (etc) float in order to have a floating point result from the divide. (Almost) Never use "float", use "double" instead it is the internal floating point default type and is more efficient. "float" should only be used when interfacing with legacy code.

    Additionally,  making those three variables float incurs some overhead for every increment (++) operation, change them to long. Then change  "n" to "double". Now the results of the divisions  will be floating point without the increment penalty.


    Good points. Thanks!
     
    Anil Philip
    Ranch Foreman
    Posts: 226
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Paul Clapham wrote:I decided to see if you could use a method reference to rehabilitate your code. And yes, you can. Here's my revised version:Note the unnecessary "whatever" variable there, it is actually necessary to allow the code to compile, for the reasons already discussed. You'll get a warning from the compiler, though. But at least it works in this context and it's a minimal change from your original try. And besides, method references are pure functional programming.

    As you see, even static methods can be used as the target of a method reference. (I assumed that your class was named "Test".) That's a bit in bad taste, though, it's generally recommended to eschew static methods as much as possible.



    Thank you sir! This is the solution I was looking for. To be able to use the original expression.
     
    Paul Clapham
    Marshal
    Posts: 28009
    94
    Eclipse IDE Firefox Browser MySQL Database
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Carey Brown wrote:There's nothing in Hackerrank that requires that streams or lambdas be used.


    I'm still in favour of experimenting with functional programming, though.
     
    Anil Philip
    Ranch Foreman
    Posts: 226
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Carey Brown wrote:There's nothing in Hackerrank that requires that streams or lambdas be used.


    It's a good exercise to use streams and lambdas because I think that they make for less complex code and fewer bugs. I never thought I would say this about streams and lambdas! they took a while to get used to.
     
    Carey Brown
    Saloon Keeper
    Posts: 10555
    83
    Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
     
    Paul Clapham
    Marshal
    Posts: 28009
    94
    Eclipse IDE Firefox Browser MySQL Database
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Carey Brown wrote:

    Yes, I didn't put in @SuppressWarnings to take care of that. But the maintainer who removed the declaration part would then be facing the compiler error which was the topic of this thread. They could ask about it here, we're always ready to help.
     
    Carey Brown
    Saloon Keeper
    Posts: 10555
    83
    Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    I was thinking of something more preemptive.
     
    Campbell Ritchie
    Marshal
    Posts: 78698
    374
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Anil Philip wrote:. . . if you start with a float, . . .

    As I said, do your counting with integer types. I don't like to see floats anywhere because of their poor precision.
     
    Campbell Ritchie
    Marshal
    Posts: 78698
    374
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Carey Brown wrote:There's nothing in Hackerrank that requires that streams or lambdas be used.

    Nor @SuppressWarnings. That template looks like pre‑Java5 code
     
    Campbell Ritchie
    Marshal
    Posts: 78698
    374
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Anil Philip wrote:. . . Are you able to see Plus Minus . . . ? . . .

    Not without logging on to that site, I am afraid. Just as well you supplied a copy for us.
     
    Anil Philip
    Ranch Foreman
    Posts: 226
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Ron McLeod wrote:Your example will not compile because forEach expects to operate on a Consumer, and a Consumer cannot return a value.
    If you wrapped it with something like System.out.println like Liutauras showed before it will also fail to compile because variables in a lambda expression need to be effectively final, and positives, zeroes, and negatives are not.



    I did not know that you must not use an expression that returns a value in a Consumer lambda. Thanks.
    Someone else mentioned (can't find their post) using an assignment to swallow the return value and get around it.
    I found that this works:






     
    Saloon Keeper
    Posts: 15276
    350
    • Likes 2
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Great, you made it work. Now, never write code like that ever again.

    Either use a simple for-loop, or use a collector.
     
    Campbell Ritchie
    Marshal
    Posts: 78698
    374
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Last night, I wrote:. . . Reading from the keyboard would be much easier with a Scanner object. . . .

    Did anybody notice the logic error in what I posted?
     
    Anil Philip
    Ranch Foreman
    Posts: 226
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Stephan van Hulst wrote:Great, you made it work. Now, never write code like that ever again.

    Either use a simple for-loop, or use a collector.


    Huh? I am quite proud of what I wrote.
     
    Campbell Ritchie
    Marshal
    Posts: 78698
    374
    • Likes 1
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Anil Philip wrote:. . . I did not know that you must not use an expression that returns a value in a Consumer lambda.

    For that sort of thing, always look in the documentation. Never trry to learn what the documentation says; you won't remember anything used less frequently than Math.max() or System.out.printf(). If you look at the documentation for Consumer, you will find it has one abstract method, and that link will show you it has void instead of a return type. The fact that it says void means it can't return anything.

    Thanks. . . .

    That's a pleasure
     
    Campbell Ritchie
    Marshal
    Posts: 78698
    374
    • Likes 1
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    A minute ago, I wrote:. . . Never try to learn what the documentation says . . .

    Except that, if you sit a certification exam, the exam syllabus will expect you to learn what the documentation says.
     
    Liutauras Vilda
    Marshal
    Posts: 8831
    631
    Mac OS X VI Editor BSD Java
    • Likes 1
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Carey Brown wrote:I was thinking of something more preemptive.


    To write an unnecessary stuff to bypass compiler doesn't sound right, primarily semantically, that introduces a necessity to write comment out of nowhere.
    I'd not write any comment here, and would not use this construct at all for the same reason.

    What I mentioned earlier to Anil, I registered yesterday to hackerank to check the problem at hand and I couldn't see in the provided template any static variables. So I'm not sure where they came from. I solved that problem by using collector to collect results and then did printing them out (didn't use any static variables), and I'd suggest Anil to refactor his code too.

    Anil, you mentioned you are doing those exercise to prepare for an interview. Now, those interviews may differ in many ways, some of those are just to solve problem and bypass some auto grader tool. Some coding challenges might be, that in addition to passing an auto grader, someone is going to review your code for its elegancy. Some interviews might be, that they don't care much about solution end-to-end, but rather a journey to it, how you decompose problem, what's your thinking process behind, how you name variables, whether you solve it in a disciplined manner and similar.. So try to be a best version of yourself when solving them, not just get unit tests to pass.
     
    Carey Brown
    Saloon Keeper
    Posts: 10555
    83
    Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
    • Likes 1
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Anil Philip wrote:

    Stephan van Hulst wrote:Great, you made it work. Now, never write code like that ever again.
    Either use a simple for-loop, or use a collector.


    Huh? I am quite proud of what I wrote.


    Ternary expressions weren't meant to be used to cause side effects but you managed to beat it into submission to get it to work. Now, what about the poor developer that comes after you that has to maintain it? He'd have to learn everything you just learned in  order to properly read the code.

    Aside from the non-intuitive constructs, I object to using static variables as accumulators. If you write it with loops then the accumulators can be local variables.
     
    Anil Philip
    Ranch Foreman
    Posts: 226
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Liutauras Vilda wrote:
    What I mentioned earlier to Anil, I registered yesterday to hackerank to check the problem at hand and I couldn't see in the provided template any static variables. So I'm not sure where they came from. I solved that problem by using collector to collect results and then did printing them out (didn't use any static variables), and I'd suggest Anil to refactor his code too.
    .



    Can you please share your code using collectors? I would like to learn how to do it that way.
    The method provided by HackerRank was static and so I had to use static member variables.
     
    Carey Brown
    Saloon Keeper
    Posts: 10555
    83
    Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Anil Philip wrote:The method provided by HackerRank was static and so I had to use static member variables.

    Not true. A simple loop, for example, would not have needed static member variables. It could use local variables.
     
    Campbell Ritchie
    Marshal
    Posts: 78698
    374
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Anil Philip wrote:. . . Can you please share your code using collectors? . . .

    I already have.

    The method provided by HackerRank was static and so I had to use static member variables.

    You could have used local variables as long as you didn't use them in a λ or anonymous class. I think the compiler error message about “non‑static” is less than crystal‑clear, and confuses people into making things static that oughtn't to be static.
    * * * * * * * * * * * * *
    On a different note, you started a very interesting discussion here
     
    Anil Philip
    Ranch Foreman
    Posts: 226
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Carey Brown wrote:

    Anil Philip wrote:The method provided by HackerRank was static and so I had to use static member variables.

    Not true. A simple loop, for example, would not have needed static member variables. It could use local variables.


    I do not wish to use loops. I want to use lambdas and streams to improve my understanding and facility with them.
     
    Everyone is a villain in someone else's story. Especially this devious tiny ad:
    a bit of art, as a gift, the permaculture playing cards
    https://gardener-gift.com
    reply
      Bookmark Topic Watch Topic
    • New Topic