Common if or ternary operator for many actions statement? - if-statement

I'm thought about how to do many actions in single ternary statement, but finished with almost the same as the common IF. So which is better, or there is no differences?
video[0].muted ? (
video[0].muted = false,
vb.attr("data-value", "loud")
) : (
video[0].muted = true,
vb.attr("data-value", "off")
);
//
if(video[0].muted) {
video[0].muted = false;
vb.attr("data-value", "loud");
} else {
video[0].muted = true;
vb.attr("data-value", "off");
}

A nice clean way of writing this that uses plain negation and a ternary would be:
var v = video[0];
// Negate the muted attribute
v.muted = !v.muted;
// And use a ternary to decide the value of this one
vb.attr("data-value", v.muted ? "off" : "loud");
Notice how the ternary is just being used here to decide which String to use.
Don't use ternarys to carry out side effects though. That's not what they're for, and abusing them never helps code readability. If you need side effects (mutating some variable), just use a plain if...else. They're much more readable.

Related

Logical OR operator result as rvalue

This code I found while doing code review. Is there any hidden problem in this code or is it just fine?
myBool = myBoolA || ( oldState == AS_PLAYING ); //code #1
Edit: One typing mistake (myBoolA in place of myBool) by me created some nasty confusion; I am really sorry for that.
Actually the code to be reviewed is :
myBool = myBool || ( oldState == AS_PLAYING ); //code #1, not myBoolA
and my suggested code is:
if( oldState == AS_PLAYING ) myBool = true; //code #2
Advantages with code#2 IMO :
better readability
if myBool is unintialized to begin with, there won't be Undefined behaviour.
myBool = myBoolA || ( oldState == AS_PLAYING ); is absolutely fine.
|| is a sequencing point in C++, so even if the expression on the right hand side depends on the left hand side (perhaps oldState is a reference to myBool or myBoolA), the behaviour will be defined.
Your recommendation in changing this to
if( oldState == AS_PLAYING ) myBool = true;
is actually functionally different (the assignment to myBool is different for example), so don't change it to that.
Finally, note that the short-circuiting nature of || is obviated if || is overloaded. So always check that when refactoring code.
myBool = myBoolA || ( oldState == AS_PLAYING ); //code #1
seems to be correct version.
Your version is not equivalent to this. How? See
if myBoolA is true and ( oldState == AS_PLAYING ) is false. myBool will still be true, but in your version, it will not be set.
After EDIT
if( oldState != AS_PLAYING ) myBool = false; //code #2 more readable IMO
This will be fine only if, myBool is initialized with true.
As per your comments later,
You can refactor as follows:
if(!myBool)
myBool = (oldState == AS_PLAYING);
this will save one extra assignment operation. when myBool is true before if

Is there a way of doing a "post switch" like operation with bool?

I have a condition like the following where I just want to have the second bool be the trigger for a single time, since this condition is invoked relatively often I don't like the idea of doing the assignment of it being false every time the condition is true so, I tried to take advantage of the order of logical AND and OR and the post increment operator. But it appears to work don't do what I expected it to do. So is there a way to make a post state switch for this line?
where firstTitleNotSet is:
bool firstTitleNotSet;
if (titleChangedSinceLastGet() || (p_firstTitleNotSet && p_firstTitleNotSet++))
The idea is that the first part is the primary trigger and the second is the trigger that only has to trigger the first time.
While I easily could do
if (titleChangedSinceLastGet() || p_firstTitleNotSet)
{
firstTitleNotSet = false;
//...
}
I don't like this as it is reassigning false when ever the conditional block is invoked.
So is there some way of "post change" the value of a bool from true to false? I know that this would work the other way around but this would negate the advantage of the method most time being the true trigger and therefor skipping the following check.
Note: The reasons for me making such considerations isntead of just taking the second case is, that this block will be called frequently so I'm looking to optimize its consumed runtime.
Well, you could do something like:
if (titleChangedSinceLastGet() ||
(p_firstTitleNotSet ? ((p_firstTitleNotSet=false), true):false))
An alternative syntax would be:
if (titleChangedSinceLastGet() ||
(p_firstTitleNotSet && ((p_firstTitleNotSet=false), true)))
Either one looks somewhat ugly. Note, however, that this is NOT the same as your other alternative:
if (titleChangedSinceLastGet() || p_firstTitleNotSet)
{
p_firstTitleNotSet = false;
//...
}
With your proposed alternative, pontificate the fact that p_firstTitleNotSet gets reset to false no matter what, even if the conditional was entered because titleChangedSinceLastGet().
A more readable way than the assignment inside a ternary operator inside an or inside an if would be just moving the operations to their own statements:
bool needsUpdate = titleChangedSinceLastGet();
if(!needsUpdate && firstTitleSet)
{
needsUpdate = true;
firstTitleSet = false;
}
if(needsUpdate)
{
//...
}
This is likely to produce very similar assembly than the less readable alternative proposed since ternary operators are mostly just syntactic sugar around if statements.
To demonstrate this I gave GCC Explorer the following code:
extern bool first;
bool changed();
int f1()
{
if (changed() ||
(first ? ((first=false), true):false))
return 1;
return 0;
}
int f2()
{
bool b = changed();
if(!b && first)
{
b = true;
first = false;
}
return b;
}
and the generated assembly had only small differences in the generated assembly after optimizations. Certainly have a look for yourself.
I maintain, however, that this is highly unlikely to make a noticeable difference in performance and that this is more for interest's sake.
In my opinion:
if(titleChangedSinceLastUpdate() || firstTitleSet)
{
firstTitleSet = false;
//...
}
is an (at least) equally good option.
You can compare the assembly of the above functions with this one to compare further.
bool f3()
{
if(changed() || first)
{
first = false;
return true;
}
return false;
}
In this kind of situation, I usually write:
bool firstTitleNotSet = true;
if (titleChangedSinceLastGet() || firstTitleNotSet)
{
if (firstTileNotSet) firstTitleNotSet = false;
//...
}
That second comparison will likely be optimized by the compiler.
But if you have a preference for a post-increment operator:
int iterationCount = 0;
if (titleChangedSinceLastGet() || iterationCount++ != 0)
{
//...
}
Note that this will be a problem if iterationCount overflows, but the same is true of the bool firstTitleNotSet that you were post-incrementing.
In terms of code readability and maintainability, I would recommend the former. If the logic of your code is sound, you can probably rely on the compiler to do a very good job optimizing it, even if it looks inelegant to you.
That should work:
int firstTitleSet = 0;
if (titleChangedSinceLastGet() || (!firstTitleSet++))
If you wish to avoid overflow you can do:
int b = 1;
if (titleChangedSinceLastGet() || (b=b*2%4))
at the first iteration b=2 while b=0 at the rest of them.

Optimize ternary operator

I came across this code written by someone else. Is this usage of the conditional operator recommended or commonly used? I feel it is less maintainable - or is it just me? Is there any alternate way of writing this?
exp_rsp_status = req.security_violation ? (dis_prot_viol_rsp && is_mstr) ?
uvc_pkg::MRSP_OKAY : uvc_pkg::MRSP_PROTVIOL : req.slv_req.size() ?
((is_mst_abort_rsp && dis_mst_abort_rsp) ||
((req.slv_req[0].get_rsp_status()==uvc_pkg::MRSP_PROTVIOL) && dis_prot_viol_rsp) ||
(is_mst_abort_rsp && req.is_pci_config_req() && dis_pcicfg_mst_abort_rsp)) ?
uvc_pkg::MRSP_OKAY : req.slv_req[0].get_rsp_status() : uvc_pkg::MRSP_OKAY;
That's just horrible code.
It's badly formatted. I don't see the hierarchy of the expression.
Even if it had good formatting, the expression would be way too complex to quickly parse with the human eye.
The intention is unclear. What's the purpose of those conditions?
So what can you do?
Use conditional statements (if).
Extract the sub-expressions, and store them in variables. Check this nice example from the refactoring catalog.
Use helper functions. If the logic is complex, use early returns. Nobody likes deep indentation.
Most importantly, give everything a meaningful name. The intention should be clear why something has to be calculated.
And just to be clear: There's nothing wrong with the ternary operator. If used judiously, it often produces code that's easier to digest. Avoid nesting them though. I occasionally use a second level if the code is crystal clear, and even then I use parentheses so my poor brain doesn't have to do extra cycles decyphering the operator precedence.
Care about the readers of your code.
Perhaps this is in a device driver's message loop and the original coder, possibly 10 years ago, didn't want jumps in the code. I hope he verified that his compiler didn't implement the ternary operator with jumps!
Examining the code, my first remark is that a sequence of ternary operators is -- like all code -- better readable when adequately formatted.
That said, I'm not sure that I parsed the OP's example correctly, which speaks against it. Even a traditional nested if-else construct would be hard to verify. This expression violates the fundamental programming paradigm: Divide and Conquer.
req.security_violation
? dis_prot_viol_rsp && is_mstr
? uvc_pkg::MRSP_OKAY
: uvc_pkg::MRSP_PROTVIOL
: req.slv_req.size()
? is_mst_abort_rsp && dis_mst_abort_rsp
|| req.slv_req[0].get_rsp_status()==uvc_pkg::MRSP_PROTVIOL
&& dis_prot_viol_rsp
|| is_mst_abort_rsp && req.is_pci_config_req() && dis_pcicfg_mst_abort_rsp
? uvc_pkg::MRSP_OKAY
: req.slv_req[0].get_rsp_status()
: uvc_pkg::MRSP_OKAY;
I wanted to check how the code looks when refactored. It sure is not shorter but I like how the speaking function names make the intent clearer (of course I guessed here). This is, to some degree, pseudo code because the variable names are probably not global so that the functions would have to have parameters, making the code less clear again. But perhaps the parameter could be a single pointer to a status or request structure or such (from which values like dis_prot_viol_rsp have been extracted). Whether or not to use a ternary when combining the different conditions is up to debate. I find it often elegant.
bool ismStrProtoViol()
{
return dis_prot_viol_rsp && is_mstr;
}
bool isIgnorableAbort()
{
return is_mst_abort_rsp && dis_mst_abort_rsp;
}
bool isIgnorablePciAbort()
{
return is_mst_abort_rsp && req.is_pci_config_req() && dis_pcicfg_mst_abort_rsp;
}
bool isIgnorableProtoViol()
{
return req.slv_req[0].get_rsp_status()==uvc_pkg::MRSP_PROTVIOL && dis_prot_viol_rsp;
}
eStatus getRspStatus()
{
eStatus ret;
if( req.security_violation )
{
ret = ismStrProtoViol() ? uvc_pkg::MRSP_OKAY : uvc_pkg::MRSP_PROTVIOL;
}
else if( req.slv_req.size() )
{
ret = isIgnorableAbort()
|| isIgnorableProtoViol()
|| isIgnorablePciAbort()
? uvc_pkg::MRSP_OKAY
: req.slv_req[0].get_rsp_status();
else
{
ret = uvc_pkg::MRSP_OKAY;
}
return ret;
}
Finally we can exploit the fact that uvc_pkg::MRSP_OKAY is kindof the default and only overwritten under certain circumstances. This eliminates a branch. Look how after some chiseling the code's reasoning is nicely visible: If it's not a security violation look closer and check the actual request status, minus empty requests and ignorable aborts.
eStatus getRspStatus()
{
eStatus ret = uvc_pkg::MRSP_OKAY;
if( req.security_violation )
{
ret = ismStrProtoViol() ? uvc_pkg::MRSP_OKAY : uvc_pkg::MRSP_PROTVIOL;
}
else if( req.slv_req.size()
&& !isIgnorableAbort()
&& !isIgnorableProtoViol()
&& !isIgnorablePciAbort()
)
{
ret = req.slv_req[0].get_rsp_status();
}
return ret;
}
What an ugly mess. I broke it out into if and else's just to see what it was doing. Not much more readable, but thought I'd post it anyways. Hopefully someone else has a more elegant solution for you. But to answer your question, don't use ternaries that complicated. No one wants to do what I just did to figure out what it's doing.
if ( req.security_violation )
{
if ( dis_prot_viol_rsp && is_mstr )
{
exp_rsp_status = uvc_pkg::MRSP_OKAY;
}
else
{
exp_rsp_status = uvc_pkg::MRSP_PROTVIOL;
}
}
else if ( req.slv_req.size() )
{
if ( ( is_mst_abort_rsp && dis_mst_abort_rsp ||
( req.slv_req[0].get_rsp_status() == uvc_pkg::MRSP_PROTVIOL && dis_prot_viol_rsp ) ||
( is_mst_abort_rsp && req.is_pci_config_req() && dis_pcicfg_mst_abort_rsp ) )
{
exp_rsp_status = uvc_pkg::MRSP_OKAY;
}
else
{
exp_rsp_status = req.slv_req[0].get_rsp_status();
}
}
else
{
exp_rsp_status = uvc_pkg::MRSP_OKAY
}
This is terrible code.
While it is often desirable to initialize a variable with a single expression (for example, so we can make it const), this is no excuse to write code like this. You can move the complex logic into a function and call it to initialize the variable.
void
example(const int a, const int b)
{
const auto mything = make_my_thing(a, b);
}
In C++11 and later, you can also use a lambda to initialize a variable.
void
example(const int a, const int b)
{
const auto mything = [a, b](){
if (a == b)
return MyThing {"equal"};
else if (a < b)
return MyThing {"less"};
else if (a > b)
return MyThing {"greater"};
else
throw MyException {"How is this even possible?"};
}();
}
Others already said how awful that code excerpt is, with nice explanations. I will just provide few more reasons why that code is bad :
if you consider one "if-else" to implement exactly one feature, then it is clear how complex that code is. In your case, I can not even count number of ifs.
It is obvious that your code is breaking breaking the single responsibility principle, which tells :
...a class or module should have one, and only one, reason to change.
unit testing that would be a nightmare, which is another red flag. And I bet that your colleague didn't even try to write unit tests for that piece of code.
Common or recommended? No.
I did something similar, but I had my reasons:
It was an argument into a third-party C function.
I was not well versed in modern C++ at the time.
I commented and formatted the f*** out of it because I knew SOMEONE besides me was going to read it...or I needed to know what it was doing years later.
It was DEBUG CODE that was never going into a release.
textprintf_ex(gw->GetBackBuffer(), font, 0, 16, WHITE, -1, "BUTTON: %s",
//If... Then Display...
(ButtonClicked(Buttons[STOP]) ? "STOP"
: (ButtonClicked(Buttons[AUTO]) ? "AUTO"
: (ButtonClicked(Buttons[TICK]) ? "TICK"
: (ButtonClicked(Buttons[BLOCK]) ? "BLOCK"
: (ButtonClicked(Buttons[BOAT]) ? "BOAT"
: (ButtonClicked(Buttons[BLINKER]) ? "BLINKER"
: (ButtonClicked(Buttons[GLIDER]) ? "GLIDER"
: (ButtonClicked(Buttons[SHIP]) ? "SHIP"
: (ButtonClicked(Buttons[GUN]) ? "GUN"
: (ButtonClicked(Buttons[PULSAR]) ? "PULSAR"
: (ButtonClicked(Buttons[RESET]) ? "RESET"
: /*Nothing was clicked*/ "NONE"
)))))))))))
);
The only reason I did not use an if-else chain was it would have made the code immense and harder to follow because all I needed to do was print a word to the screen.

c++ function check true condition

I make a function call and when it returns false, I continue to check indefinitely until it returns true. Is the following code is fine?
while(true)
{
bool result = func();
if(result == false)
continue;
else
break;
}
How about getting rid of the break and continue. It is not considered very nice to use them (especially when not required):
bool result;
do
{
result = func();
if(result == false) {
// Supposedly you want to do something here...?
}
} while(result == false);
Of course you can use ! instead of false to save some bytes in your source code. But I suppose that does not really matter at this point.
You could do that, but why not just:
while(!func())
{
// do what you want to do...
}
Why not use
while (!func());
instead? Some folk don't like to see an empty while and may therefore prefer #dwxw's solution.
You can make it shorter.
do
{
} while (!func());

C++ boolean logic error possibly caused by if statements

Here is an extremely simplified version of a section of code that I am having trouble with.
int i = 0;
int count = 0;
int time = 50;
int steps = 1000;
double Tol = 0.1;
bool crossRes = false;
bool doNext = true;
for (int i=0; i<steps; i++) {
//a lot of operations are done here, I will leave out the details, the only
//important things are that "dif" is calculated each time and doNext either
//stays true or is switched to false
if (doNext = true) {
if (dif <= Tol) count++;
if (count >= time) {
i = steps+1;
crossRes = true;
}
}
}
if (crossRes = true) {
printf("Nothing in this loop should happen if dif is always > Tol
because count should never increment in that case, right?");
}
My issue is that every time it gets done with the for loop, it executes the statements inside the "if (crossRes = true)" brackets even if count is never incremented.
You've made a common (and quite frustrating) mistake:
if (crossRes = true) {
This line assigns crossRes to true and returns true. You're looking to compare crossRes with true, which means you need another equals sign:
if (crossRes == true) {
Or more concisely:
if (crossRes) {
I stand corrected:
if (crossRes)
You wouldn't have this problem if your condition was
if (true = crossRes)
because it wouldn't compile.
`crossRes = true` always evaluates to `true` because it's an assignment, to `true`.
You want `crossRes == true`:
if (crossRes == true) {
printf("Nothing in this loop should happen if dif is always > Tol
because count should never increment in that case, right?");
}
= is assignment, == is equality comparison. You want:
if (crossRes == true) {
You make the same mistake here:
if (doNext = true) { // Bad code
The other answers here have told you the problem. Often your compiler will warn you but a way to ensure that you do not do this is to put the constant term on the left
true == crossRes
that way you get a compiler error instead of a warning and so it can't escape unnoticed since
true = crossRes
wont compile.
First, although a number of people have pointed to the problem with if (crossRes = true), for some reason they haven't (yet, anyway) pointed to the same problem with if (doNext = true).
I'll stick to pointing out that you really want if (crossRes) rather than if (crossRes == true) (or even if (true == crossRes)).
The first reason is that it avoids running into the same problem from a simple typo.
The second is that the result of the comparison is a bool -- so if if (crossRes==true) is necessary, you probably need if (((((crossRes == true) == true) == true) == true) just to be sure (maybe a few more -- you never know). This would, of course, be utterly silly -- you're starting with a bool, so you don't need a comparison to get a bool.
I'd also note for the record, that if you insist on doing a comparison at all, you should almost always use if (x != false) rather than if (x == true). Though it doesn't really apply in C++, in old C that doesn't have an actual Boolean type, any integer type can be used -- but in this case, a comparison to true can give incorrect results. At least normally, false will be 0 and true will be 1 -- but when tested, any non-zero value will count as equivalent to true. For example:
int x = 10;
if (x) // taken
if (x == true) // not taken, but should be.
If you're not starting with a Boolean value as you are here, then the if (<constant> <comparison> <variable>) makes sense and is (IMO) preferred. But when you're starting with a Boolean value anyway, just use it; don't do a comparison to produce another of the same.