I have this code:
val leftEnoughRoom = if(fx1 > eachSideBesidesFace){
true
}else{
false
}
And get the warning:
This inspection reports if statements which can be simplified to single statements. For example:
if (foo()) {
return true
} else {
return false
}
can be simplified to return foo().
What does it want me to do? When I do:
if(fx1 > eachSideBesidesFace){
val leftEnoughRoom = true
}else{
val leftEnoughRoom = false
}
Then leftEnoughRoom is not reachable below any more
fx1 > eachSideBesidesFace
is a boolean statement. You don't need the if-else:
val leftEnoughRoom = fx1 > eachSideBesidesFace
As a sidenote, you can click the underlined expression, hit Alt+Enter and then have Android Studio automatically optimize the code.
Related
The source below should return FALSE if we have numbers such as 1,2,3,... and TRUE if the value is NA (i.e., missing) or Inf (i.e., 1/0). Instead, running the function repeated times gives random combinations of T/F for the vector c(1,NA,3,Inf,5), and the correct output should be F/T/F/T/F.
I am quite sure that I wrote a function that is correct, and there is no randomness in the code.
How do you debug/test a function like this?
How do make sure that this is not a strange error with the C++ compiler? I am using vanilla Ubuntu 20.04.
Calling the is_na_or_inf function from R:
> is_na_or_inf(c(1,NA,3,Inf,5))
[1] TRUE TRUE TRUE TRUE TRUE
> is_na_or_inf(c(1,NA,3,Inf,5))
[1] FALSE TRUE FALSE TRUE TRUE
> is_na_or_inf(c(1,NA,3,Inf,5))
[1] TRUE TRUE TRUE TRUE TRUE
This is the corresponding C++ code (called with the "source" button in RStudio is)
#include <cpp11.hpp>
#include <cpp11/doubles.hpp>
#include <cpp11/logicals.hpp>
using namespace cpp11;
[[cpp11::register]] logicals is_na_or_inf(SEXP x)
{
int nobs = Rf_length(x);
double *px = REAL(x);
bool anyNAInf = true;
writable::logicals is_na_inf(anyNAInf ? nobs : 1);
for (int i = 0; i < nobs; ++i)
{
double x_tmp = px[i];
if (std::isnan(x_tmp))
{
is_na_inf[i] = true;
}
else if (std::isinf(x_tmp))
{
is_na_inf[i] = true;
}
}
return is_na_inf;
}
I have a method inside a class that is not returning a value.
These are the relevant variables that are being used in the method, they are in the private part of the class
int hieght_of_plane = 0 ;
int position_of_plane = 0 ;
bool landing_gear = true ;
bool is_flying = false ;
bool is_alive = true ;
And here is the method that is not returning true or false, it is in the public section of the class.
bool check_for_alive()
{
if (is_flying == false)
{
return true ;
}
if (is_flying == true)
{
if (hieght_of_plane <= 3)
{
if (landing_gear == false)
{
is_alive = false ;
return false ;
}
else if (landing_gear == true)
{
return true ;
}
}
}
}
The method seems to not do anything and then I get the no return value error
warning: control reaches end of non-void function [-Wreturn-type]
I assume that it should return false in this instance because is_flying = false so the method should return false, but it isn't.
The case that falls through is when flying == true and hieght_of_plane is greater than 3.
if (is_flying == true)
{
if (hieght_of_plane <= 3)
{
The 2nd if statement does not have an else, which is necessary for returning a value.
Edit 1: An else clause
The else clause should be used for the "not" case of the if statement.
For example:
if (is_flying == false)
{
return true;
}
else // This means is_flying == true
{
if (hieght_of_plane <= 3)
{
if (landing_gear == false)
{
is_alive = false ;
return false ;
}
else // implies landing_gear == true
{
return true ;
}
else // implies hieght > 3
{
return ????
}
}
You could also reduce this down to one Boolean expression.
Edit 2: Simplification
There are two functionalities here: Return true/false for a combination of conditions and to set is_alive based on a condition.
Let's say that one condition is true, all others is false.
bool check_for_alive()
{
if (is_flying && (height_of_plane <= 3) && (landing_gear == false))
{
is_alive = false;
}
return is_flying && (height_of_plane <= 3) && (landing_gear == true);
}
Note: The above does not consider the case of `(height_of_plane > 3), since this is not specified in the OP's original code.
the control flow would reach the end of the function when is_flying is true and hieght_of_plane is > 3. you MUST return something there.
and one more thing is the you don't always need to check that if (something == true) instead if (something) would enough, I've pointed some more below the code.
bool check_for_alive() {
if (!is_flying)
return true;
// if you reached here is_flying is true no need to check
if (hieght_of_plane <= 3) {
if (!landing_gear) {
is_alive = false;
return false;
} else {
// if you're here landing_gear is false no need to check
return true;
}
}
// what to return if we reach here? yes the control flow could reach
// here when is_flying is true and hieght_of_plane is > 3
// you must return something here.
}
My code is as below
private fun validateInput(): Boolean {
if (etReportRow1.text.toString() == ""
|| etReportRow2.text.toString() == ""
|| etReportRow3.text.toString() == "")
return false
else
return true
}
The compiler tell me
Redundant 'if' statement less... (Ctrl+F1) This inspection reports if
statements which can be simplified to single statements. For example:
if (foo()) { return true } else { return false } can be
simplified to return foo().
Won't the suggested code go into loop?
All statments in the form:
if(condition){
return false
} else {
return true
}
can be simplified into:
return !condition
So in your case it would lead to:
return !(etReportRow1.text.toString() == "" || etReportRow2.text.toString() == "" || etReportRow3.text.toString() == "")
Or:
return
etReportRow1.text.toString().isNotEmpty() &&
etReportRow2.text.toString().isNotEmpty() &&
etReportRow3.text.toString().isNotEmpty()
Note: the isNotEmpty() is an extension method:
public inline fun CharSequence.isNotEmpty(): Boolean = length > 0
To avoid duplicate code you could also use a Sequence:
public fun validateInput() = sequenceOf(etReportRow1, etReportRow2, etReportRow3)
.map { it.text.toString() }
.all { it.isNotEmpty() }
Because a boolean expression evaluates to a boolean value, you can simply return the result of the expression itself, without having to explicitly return true or false.
You can further simplify things using the following single-expression function:
private fun validateInput() = etReportRow1.text.toString() != "" &&
etReportRow2.text.toString() != "" &&
etReportRow3.text.toString() != ""
try
return !(etReportRow1.text.toString() == "" || etReportRow2.text.toString() == "" || etReportRow3.text.toString() == "")
I think this should work:
private fun validateInput() = !(etReportRow1.text.toString.isEmpty()
|| etReportRow2.text.toString().isEmpty()
|| etReportRow3.text.toString().isEmpty() )
Even more concise:
public fun validateInput() = setOf(
etReportRow1, etReportRow2, etReportRow3
).none {
"${it.text}".isEmpty()
}
After watching carefully the following code I can't see why the compiler is warning me with "warning: control reaches end of non-void function".
bool Foam::solidMagnetostaticModel::read()
{
if (regIOobject::read())
{
if (permeabilityModelPtr_->read(subDict("permeability")) && magnetizationModelPtr_->read(subDict("magnetization")))
{
return true;
}
}
else
{
return false;
}
}
I can't see where is the problem, the else statement should care for returning false in every case which the first if is not true.
Trace the code path when regIOobject::read() is true, but either of permeabilityModelPtr_->read(subDict("permeability")) or magnetizationModelPtr_->read(subDict("magnetization")) is false. In that case, you enter the top if block (excluding the possibility of entering its attached else block), but then fail to enter the nested if block:
bool Foam::solidMagnetostaticModel::read()
{
if (regIOobject::read())
{
// Cool, read() was true, now check next if...
if (permeabilityModelPtr_->read(subDict("permeability")) && magnetizationModelPtr_->read(subDict("magnetization")))
{
return true;
}
// Oh no, it was false, now we're here...
}
else
{
// First if was true, so we don't go here...
return false;
}
// End of function reached, where is the return???
}
The minimalist fix is to just remove the else { } wrapping, so any fallthrough ends up at return false;:
bool Foam::solidMagnetostaticModel::read()
{
if (regIOobject::read())
{
// Cool, read() was true, now check next if...
if (permeabilityModelPtr_->read(subDict("permeability")) && magnetizationModelPtr_->read(subDict("magnetization")))
{
return true;
}
// Oh no, it was false, now we're here...
}
// Oh, but we hit return false; so we're fine
return false;
}
Alternatively, avoid specifically mentioning true or false at all, since your function is logically just a result of anding three conditions together:
bool Foam::solidMagnetostaticModel::read()
{
// No need to use ifs or explicit references to true/false at all
return regIOobject::read() &&
permeabilityModelPtr_->read(subDict("permeability")) &&
magnetizationModelPtr_->read(subDict("magnetization"));
}
The nested if is the problem.
When that branch is not taken, there is no other paths to take
the else statement should care for returning false in every case which the first if is not true.
Correct, but what if the first if condition is true, but the second if condition is not?
That is: What if regIOobject::read() returns true, but permeabilityModelPtr_->read(subDict("permeability")) returns false?
Then the flow of control enters the first if block, does not return, but does not enter the else block (because the first condition was true), so it just falls off the end of the function without hitting a return statement.
If you want the else { return false; } part to apply to either condition, you could just naively copy/paste it:
if (COND1) {
if (COND2) {
return true;
} else {
return false;
}
} else {
return false;
}
But that's quite a bit of code duplication. A better solution is to replace the nested if by a single condition:
if (COND1 && COND2) {
return true;
} else {
return false;
}
There's still some duplication: Both branches consist of a return statement followed by some expression.
We can factor out the common parts (return) and push the condition into the expression:
return COND1 && COND2 ? true : false;
But ? true : false is redundant: If the condition is true, evaluate to true, else evaluate to false? Well, that's just what the condition itself does:
return COND1 && COND2;
Or with your concrete expressions:
return regIOobject::read()
&& permeabilityModelPtr_->read(subDict("permeability"))
&& magnetizationModelPtr_->read(subDict("magnetization"));
I'm sure you've been there. You want to say "if flib do this, if flob do that, if flab do diet, etc" where any number of them can be true, then at the end you want an "if you didn't do ANY of them".
For example (the examples below are in Swift, as I've been playing with it, but I think the situation is the same in most languages):
let thing = 101
var isInteresting = false
if (thing % 3 == 0) {
println("\"\(thing)\" is a multiple of three.")
isInteresting = true
}
if (thing > 100) {
println("\"\(thing)\" is greater than one hundred.")
isInteresting = true
}
if (thing > 1000) {
println("\"\(thing)\" is greater than one thousand.")
isInteresting = true
}
if !isInteresting {
println("\"\(thing)\" is boring.")
}
I find keeping track of a boolean to tell me whether I did anything or not kinda ungainly.
The only other way I came up with was this:
let thing = 101
let isAMultipleOfThree = (thing % 3 == 0)
let isGreaterThan100 = (thing > 100)
let isGreaterThan1000 = (thing > 1000)
if isAMultipleOfThree {
println("\"\(thing)\" is a multiple of three.")
}
if isGreaterThan100 {
println("\"\(thing)\" is greater than one hundred.")
}
if isGreaterThan1000 {
println("\"\(thing)\" is greater than one thousand.")
}
if !(isAMultipleOfThree || isGreaterThan100 || isGreaterThan1000 ) {
println("\"\(thing)\" is boring.")
}
but if anything that's worse (if you add a new clause you need to remember to add it in three places.
So my question is, is there a neat, succinct way of doing this?
I'm dreaming of an imaginary switch-like statement:
switchif { //Would have fallthrough where every case condition is checked
case thing % 3 == 0:
println("\"\(thing)\" is a multiple of three.")
case thing >100 :
println("\"\(thing)\" is greater than one hundred.")
case thing > 1000:
println("\"\(thing)\" is greater than one thousand.")
none: //Unlike 'default' this would only occur if none of the above did
println("\"\(thing)\" is boring.")
}
It's a good question that does not have a perfect answer. However, here's one other idea in addition to those you suggest: Encapsulate the testing machinery in a procedure to allow the calling code at least to be a bit more streamlined.
Specifically, for your example, the calling code can be this:
if (! doInterestingStuff(101)) {
println("\"\(thing)\" is boring.");
}
If testing is encapsulated into a procedure:
public boolean doInterestingStuff(int thing) {
var isInteresting = false
if (thing % 3 == 0) {
println("\"\(thing)\" is a multiple of three.")
isInteresting = true
}
if (thing > 100) {
println("\"\(thing)\" is greater than one hundred.")
isInteresting = true
}
if (thing > 1000) {
println("\"\(thing)\" is greater than one thousand.")
isInteresting = true
}
return isInteresting
}
I'm not sure how you'd do this in Swift, but since you didn't give a language tag I'll answer in C++.
The key to this is that && is short circuiting, and the second part won't be evaluated when the first part is false. It's the same idea as your boolean flag, but it's a little more automated.
struct Tracker
{
Tracker() : any(false) { }
bool operator()() { any = true; return true; }
bool any;
};
int thing = 101;
Tracker tracker;
if (thing % 3 == 0 && tracker()) {
printf("\"%d\" is a multiple of three.\n", thing);
}
if (thing > 100 && tracker()) {
printf("\"%d\" is greater than one hundred.\n", thing);
}
if (thing > 1000 && tracker()) {
printf("\"%d\" is greater than one thousand.\n", thing);
}
if (!tracker.any) {
printf("\"%d\" is boring.\n", thing);
}
See it in action: http://ideone.com/6MQYY2
kjhughes' answer inspired me a little:
Perhaps one could write a global function that accepts an indeterminate number of key-value pairs (or even just two element arrays), where the key is a comparison and the value is the statement to run if it's true. Then return false if none of them were run, otherwise true.
Update:
Tried it, it's horrible!
//Function:
func ifNone(ifNoneFunc:()->Void, tests: Bool...)
{
var oneTestPassed = false
for test in tests
{
oneTestPassed |= test
}
if(!oneTestPassed)
{
ifNoneFunc()
}
}
//Example:
let thisThing = 7
ifNone(
{
println("\(thisThing) is boring")
},
{
if(thisThing % 10 == 0)
{
println("\"\(thisThing)\" is a multiple of 10")
return true
}
else
{
return false
}
}(),
{
if(thisThing % 3 == 0)
{
println("\"\(thisThing)\" is a multiple of 3")
return true
}
else
{
return false
}
}(),
{
if(thisThing > 1_000_000)
{
println("\"\(thisThing)\" is over a million!!")
return true
}
else
{
return false
}
}()
)