statement not allowed after 'return', 'break', 'raise', 'continue' - static-analysis

proc myproc(T: typedesc): string =
when T is bool:
return "bool"
when T is float:
return "float"
echo myproc(bool)
Error: statement not allowed after 'return', 'break', 'raise',
'continue' or proc call with noreturn pragma
using elif works, but is it not unreasonable to require a linked when/else statement ?

The real question is: What would anyone gain from allowing this code to compile, when all you have to do is to write
when T is bool:
return "bool"
elif T is float:
return "float"
Your code does not get shorter, nor can you do things that would not be possible otherwise. So, allowing your code to compile would only place an additional burden on the compiler without any return of investment. My code also makes the intention clearer: Either do one thing or the other, while your code says Maybe do this, and maybe do that.
I don't know the implementation details, but I would assume that it is not trivial for the compiler to prove that T is bool and T is float are disjoint.
Edit: Proof that there is no benefit
Assume our body starts with
when T is bool: return "bool"
Obviously, if T is bool evaluates to true at compile time, an unconditional return statement gets compiled and there may not be statements after it. That is to say, all statements coming after the when block must be swallowed at compile time unless the above condition is false.
I believe there are basically two different statements that may be swallowed at compile time: other when statements and calls to templates or macros (they may return an empty AST node). I already showed that a succeeding when may be replaced by an elif without any loss of expressiveness. Now let's look at a macro or template call:
when T is bool: return "bool"
call(T)
This can easily be fixed by rewriting it as:
when T is bool: return "bool"
else: call(T)
I admit that we have more code here, but I do not see any real gain we would get from leaving out the else:.
If you are still not convinced, I invite you to give example code where you think you would have an actual benefit, so that we can discuss it.

Related

How to avoid checking each condition inside if statement which contains complex operation

Let's say I have this code:
if (condition1 || condition2) {
some_complex_operation(); // memory or time wise, doesn't matter
if (condition1) {
doJob1();
}
if (condition2) {
doJob2();
}
}
Now of course normal procedure here would be to leave out the first if condition, but since I want my complex operation to happen only when one of conditions is satisfied I'd want to avoid doing it every time.
Is there syntactically better way to rewrite this part of the code?
Unless the check for your conditions is expensive, I think your code is fine as it is (and if the check is expensive, you could convert them into booleans before the first if).
Alternatives would be:
move the call to the complex operation inside both if's and remove the outer if, but I like it better as it is now, because it's in one block.
depending on the values of your conditions, you could use a switch statement instead of the two if's, but that won't make much of a difference.
If both conditions can't be true at the same time you could place an else before the second inner if. You could even remove the second check and only use else but then you'd have to make sure the number of conditions never changes.
And of course, in general with or, always place the condition that occurs the most first (in both cases) so there's no need to check the second condition when the first evaluates to true.

TCL how to require both operands to determine result in IF statement

new to TCL and running into a short circuit issue it seems. Coming from vbscript, I'm able to perform this properly, but trying to convert to a TCL script I'm having issues with the short circuit side effect and have been trying to find the proper way of doing this.
In the following snippet, I want to execute "do something" only if BOTH sides are true, but because of short circuiting, it will only evaluate the second argument if the first fails to determine the value of the expression.
if {$basehour != 23 && $hours != 0} {
do something
}
Maybe I'm not searching for the right things, but so far I've been unable to find the solution. Any tips would be appreciated.
The && operator always does short-circuiting in Tcl (as it does in C and Java and a number of other languages too). If you want the other version and can guarantee that both sub-expressions yield booleans (e.g., they come from equality tests such as you're doing) then you can use the & operator instead, which does bit-wise AND and will do what you want when working on bools. If you're doing this, it's wise to put parentheses around the sub-expressions for clarity; while everyone remember the precedence of == with respect to &&, the order w.r.t. & is often forgotten. (The parentheses are free in terms of execution cost.)
if {($basehour != 23) & ($hours != 0)} {
do something
}
However, it's usually not necessary to do this. If you're wanting an AND that you're feeding into a boolean test (e.g., the if command's expression) then there's no reason to not short-circuit, as in your original code; if the first clause gives false, the second one won't change what value the overall expression produces.

style opinion re. empty If block

I'm trying to curb some of the bad habits of a self-proclaimed "senior programmer." He insists on writing If blocks like this:
if (expression) {}
else {
statements
}
Or as he usually writes it in classic ASP VBScript:
If expression Then
Else
statements
End If
The expression could be something as easily negated as:
if (x == 0) {}
else {
statements
}
Other than clarity of coding style, what other reasons can I provide for my opinion that the following is preferred?
if (x != 0) {
statements
}
Or even the more general case (again in VBScript):
If Not expression Then
statements
End If
Reasons that come to my mind for supporting your opinion (which I agree with BTW) are:
Easier to read (which implies easier to understand)
Easier to maintain (because of point #1)
Consistent with 'established' coding styles in most major programming languages
I have NEVER come across the coding-style/form that your co-worker insists on using.
I've tried it both ways. McConnell in Code Complete says one should always include both the then and the else to demonstrate that one has thought about both conditions, even if the operation is nothing (NOP). It looks like your friend is doing this.
I've found this practice to add no value in the field because unit testing handles this or it is unnecessary. YMMV, of course.
If you really want to burn his bacon, calculate how much time he's spending writing the empty statements, multiply by 1.5 (for testing) and then multiply that number by his hourly rate. Send him a bill for the amount.
As an aside, I'd move the close curly bracket to the else line:
if (expression) {
} else {
statements
}
The reason being that it is tempting to (or easy to accidentally) add some statement outside the block.
For this reason, I abhor single-line (bare) statements, of the form
if (expression)
statement
Because it can get fugly (and buggy) really fast
if (expression)
statement1
statement2
statement2 will always run, even though it might look like it should be subject to expression. Getting in the habit of always using brackets will kill this stumbling point dead.

Why use short-circuit code?

Related Questions: Benefits of using short-circuit evaluation, Why would a language NOT use Short-circuit evaluation?, Can someone explain this line of code please? (Logic & Assignment operators)
There are questions about the benefits of a language using short-circuit code, but I'm wondering what are the benefits for a programmer? Is it just that it can make code a little more concise? Or are there performance reasons?
I'm not asking about situations where two entities need to be evaluated anyway, for example:
if($user->auth() AND $model->valid()){
$model->save();
}
To me the reasoning there is clear - since both need to be true, you can skip the more costly model validation if the user can't save the data.
This also has a (to me) obvious purpose:
if(is_string($userid) AND strlen($userid) > 10){
//do something
};
Because it wouldn't be wise to call strlen() with a non-string value.
What I'm wondering about is the use of short-circuit code when it doesn't effect any other statements. For example, from the Zend Application default index page:
defined('APPLICATION_PATH')
|| define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));
This could have been:
if(!defined('APPLICATION_PATH')){
define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));
}
Or even as a single statement:
if(!defined('APPLICATION_PATH'))
define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));
So why use the short-circuit code? Just for the 'coolness' factor of using logic operators in place of control structures? To consolidate nested if statements? Because it's faster?
For programmers, the benefit of a less verbose syntax over another more verbose syntax can be:
less to type, therefore higher coding efficiency
less to read, therefore better maintainability.
Now I'm only talking about when the less verbose syntax is not tricky or clever in any way, just the same recognized way of doing, but in fewer characters.
It's often when you see specific constructs in one language that you wish the language you use could have, but didn't even necessarily realize it before. Some examples off the top of my head:
anonymous inner classes in Java instead of passing a pointer to a function (way more lines of code).
in Ruby, the ||= operator, to evaluate an expression and assign to it if it evaluates to false or is null. Sure, you can achieve the same thing by 3 lines of code, but why?
and many more...
Use it to confuse people!
I don't know PHP and I've never seen short-circuiting used outside an if or while condition in the C family of languages, but in Perl it's very idiomatic to say:
open my $filehandle, '<', 'filename' or die "Couldn't open file: $!";
One advantage of having it all in one statement is the variable declaration. Otherwise you'd have to say:
my $filehandle;
unless (open $filehandle, '<', 'filename') {
die "Couldn't open file: $!";
}
Hard to claim the second one is cleaner in that case. And it'd be wordier still in a language that doesn't have unless
I think your example is for the coolness factor. There's no reason to write code like that.
EDIT: I have no problem with doing it for idiomatic reasons. If everyone else who uses a language uses short-circuit evaluation to make statement-like entities that everyone understands, then you should too. However, my experience is that code of that sort is rarely written in C-family languages; proper form is just to use the "if" statement as normal, which separates the conditional (which presumably has no side effects) from the function call that the conditional controls (which presumably has many side effects).
Short circuit operators can be useful in two important circumstances which haven't yet been mentioned:
Case 1. Suppose you had a pointer which may or may not be NULL and you wanted to check that it wasn't NULL, and that the thing it pointed to wasn't 0. However, you must not dereference the pointer if it's NULL. Without short-circuit operators, you would have to do this:
if (a != NULL) {
if (*a != 0) {
⋮
}
}
However, short-circuit operators allow you to write this more compactly:
if (a != NULL && *a != 0) {
⋮
}
in the certain knowledge that *a will not be evaluated if a is NULL.
Case 2. If you want to set a variable to a non-false value returned from one of a series of functions, you can simply do:
my $file = $user_filename ||
find_file_in_user_path() ||
find_file_in_system_path() ||
$default_filename;
This sets the value of $file to $user_filename if it's present, or the result of find_file_in_user_path(), if it's true, or … so on. This is seen perhaps more often in Perl than C, but I have seen it in C.
There are other uses, including the rather contrived examples which you cite above. But they are a useful tool, and one which I have missed when programming in less complex languages.
Related to what Dan said, I'd think it all depends on the conventions of each programming language. I can't see any difference, so do whatever is idiomatic in each programming language. One thing that could make a difference that comes to mind is if you had to do a series of checks, in that case the short-circuiting style would be much clearer than the alternative if style.
What if you had a expensive to call (performance wise) function that returned a boolean on the right hand side that you only wanted called if another condition was true (or false)? In this case Short circuiting saves you many CPU cycles. It does make the code more concise because of fewer nested if statements. So, for all the reasons you listed at the end of your question.
The truth is actually performance. Short circuiting is used in compilers to eliminate dead code saving on file size and execution speed. At run-time short-circuiting does not execute the remaining clause in the logical expression if their outcome does not affect the answer, speeding up the evaluation of the formula. I am struggling to remember an example. e.g
a AND b AND c
There are two terms in this formula evaluated left to right.
if a AND b evaluates to FALSE then the next expression AND c can either be FALSE AND TRUE or FALSE AND FALSE. Both evaluate to FALSE no matter what the value of c is. Therefore the compiler does not include AND c in the compiled format hence short-circuiting the code.
To answer the question there are special cases when the compiler cannot determine whether the logical expression has a constant output and hence would not short-circuit the code.
Think of it this way, if you have a statement like
if( A AND B )
chances are if A returns FALSE you'll only ever want to evaluate B in rare special cases. For this reason NOT using short ciruit evaluation is confusing.
Short circuit evaluation also makes your code more readable by preventing another bracketed indentation and brackets have a tendency to add up.

What to put in the IF block and what to put in the ELSE block?

This is a minor style question, but every bit of readability you add to your code counts.
So if you've got:
if (condition) then
{
// do stuff
}
else
{
// do other stuff
}
How do you decide if it's better like that, or like this:
if (!condition) then
{
// do other stuff
{
else
{
// do stuff
}
My heuristics are:
Keep the condition positive (less
mental calculation when reading it)
Put the most common path into the
first block
I prefer to put the most common path first, and I am a strong believer in nesting reduction so I will break, continue, or return instead of elsing whenever possible. I generally prefer to test against positive conditions, or invert [and name] negative conditions as a positive.
if (condition)
return;
DoSomething();
I have found that by drastically reducing the usage of else my code is more readable and maintainable and when I do have to use else its almost always an excellent candidate for a more structured switch statement.
Two (contradictory) textbook quotes:
Put the shortest clause of an if/else
on top
--Allen Holub, "Enough Rope to Shoot Yourself in the Foot", p52
Put the normal case after the if rather than after the else
--Steve McConnell, "Code Complete, 2nd ed.", p356
I prefer the first one. The condition should be as simple as possible and it should be fairly obvious which is simpler out of condition and !condition
It depends on your flow. For many functions, I'll use preconditions:
bool MyFunc(variable) {
if (variable != something_i_want)
return false;
// a large block of code
// ...
return true;
}
If I need to do something each case, I'll use an if (positive_clause) {} else {} format.
If the code is to check for an error condition, I prefer to put that code first, and the "successful" code second; conceptually, this keeps a function call and its error-checking code together, which makes sense to me because they are related. For example:
if (!some_function_that_could_fail())
{
// Error handling code
}
else
{
// Success code
}
I agree with Oli on using a positive if clause when possible.
Just please never do this:
if (somePositiveCondition)
else {
//stuff
}
I used to see this a lot at one place I worked and used to wonder if one of the coders didn't understand how not works...
When I am looking at data validation, I try to make my conditions "white listing" - that is, I test for what I will accept:
if DataIsGood() then
DoMyNormalStuff
else
TakeEvasiveAction
Rather than the other way around, which tends to degenerate into:
if SomeErrorTest then
TakeSomeEvasiveAction
else if SomeOtherErrorCondition then
CorrectMoreStupidUserProblems
else if YetAnotherErrorThatNoOneThoughtOf then
DoMoreErrorHandling
else
DoMyNormalStuff
I know this isn't exactly what you're looking for, but ... A lot of developers use a "guard clause", that is, a negative "if" statement that breaks out of the method as soon as possible. At that point, there is no "else" really.
Example:
if (blah == false)
{
return; // perhaps with a message
}
// do rest of code here...
There are some hard-core c/c++/assembly guys out there that will tell you that you're destroying your CPU!!! (in many cases, processors favor the "true" statement and try to "prefetch" the next thing to do... so theoretically any "false" condition will flush the pipe and will go microseconds slower).
In my opinion, we are at the point where "better" (more understandable) code wins out over microseconds of CPU time.
I think that for a single variable the not operator is simple enough and naming issues start being more relevant.
Never name a variable not_X, if in need use a thesaurus and find an opposite. I've seen plenty of awful code like
if (not_dead) {
} else {
}
instead of the obvious
if (alive) {
} else {
}
Then you can sanely use (very readable, no need to invert the code blocks)
if (!alive) {
} else {
}
If we're talking about more variables I think the best rule is to simplify the condition. After a while projects tend to get conditions like:
if (dead || (!dead && sleeping)) {
} else {
}
Which translates to
if (dead || sleeping) {
} else {
}
Always pay attention to what conditions look like and how to simplify them.
Software is knowledge capture. You're encoding someone's knowledge of how to do something.
The software should fit what's "natural" for the problem. When in doubt, ask someone else and see what people actually say and do.
What about the situation where the "common" case is do nothing? What then
if( common ) {
// pass
}
else {
// great big block of exception-handling folderol
}
Or do you do this?
if( ! common ) {
// great big block of except-handling folderol
}
The "always positive" rule isn't really what you want first. You want to look at rules more like the following.
Always natural -- it should read like English (or whatever the common language in your organization is.)
Where possible, common cases first -- so they appear common.
Where possible use positive logic; negative logic can be used where it's commonly said that way or where the common case is a do-nothing.
If one of the two paths is very short (1 to 10 lines or so) and the other is much longer, I follow the Holub rule mentioned here and put the shorter piece of code in the if. That makes it easier to see the if/else flow on one screen when reviewing the code.
If that is not possible, then I structure to make the condition as simple as possible.
For me it depends on the condition, for example:
if (!PreserveData.Checked)
{ resetfields();}
I tend to talk to my self with what I want the logic to be and code it to the little voice in my head.
You can usually make the condition positive without switching around the if / else blocks.
Change
if (!widget.enabled()) {
// more common
} else {
// less common
}
to
if (widget.disabled()) {
// more common
} else {
// less common
}
Intel Pentium branch prediction pre-fetches instructions for the "if" case. If it instead follows the "else" branch: it has the flush the instruction pipeline, causing a stall.
If you care a lot about performance: put the most likely outcome in the 'if' clause.
Personally i write it as
if (expected)
{
//expected path
}
else
{
//fallback other odd case
}
If you have both true and false conditions then I'd opt for a positive conditional - This reduces confusion and in general I believe makes your code easier to read.
On the other hand, if you're using a language such as Perl, and particularly if your false condition is either an error condition or the most common condition, you can use the 'unless' structure, which executes the code block unless the condition is true (i.e. the opposite of if):
unless ($foo) {
$bar;
}
First of all, let's put aside situations when it is better to avoid using "else" in the first place (I hope everyone agrees that such situations do exist and determining such cases probably should be a separate topic).
So, let's assume that there must be an "else" clause.
I think that readability/comprehensibility imposes at least three key requirements or rules, which unfortunately often compete with each other:
The shorter is the first block (the "if" block) the easier is it to grasp the entire "if-else" construct. When the "if" block is long enough, it becomes way too easy to overlook existence of "else" block.
When the "if" and "else" paths are logically asymmetric (e.g. "normal processing" vs. "error processing"), in a standalone "if-else" construct it does not really matter much which path is first and which is second. However, when there are multiple "if-else" constructs in proximity to each other (including nesting), and when all those "if-else" constructs have asymmetry of the same kind - that's when it is very important to arrange those asymmetric paths consistently.
Again, it can be "if ... normal path ... else ... abnormal path" for all, or "if ... abnormal path ... else ... normal path" for all, but it should not be a mix of these two variants.
With all other conditions equal, putting the normal path first is probably more natural for most human beings (I think it's more about psychology than aesthetics :-).
An expression that starts with a negation usually is less readable/comprehensible than an expression that doesn't.
So, we have these three competing requirements/rules, and the real question is: which of them are more important than others. For Allen Holub the rule #1 is probably the most important one. For Steve McConnell - it is the rule #2. But I don't think that you can really choose only one of these rules as a single quideline.
I bet you've already guessed my personal priorities here (from the way I ordered the rules above :-).
My reasons are simple:
The rule #1 is unconditional and impossible to circumvent. If one of the blocks is so long that it runs off the screen - it must become the "else" block. (No, it is not a good idea to create a function/method mechanically just to decrease the number of lines in an "if" or "else" block! I am assuming that each block already has a logically justifiable minimum amount of lines.)
The rule #2 involves a lot of conditions: multiple "if-else" constructs, all having asymmetry of the same kind, etc. So it just does not apply in many cases.
Also, I often observe the following interesting phenomenon: when the rule #2 does apply and when it is used properly, it actually does not conflict with the rule #1! For example, whenever I have a bunch of "if-else" statements with "normal vs. abnormal" asymmetry, all the "abnormal" paths are shorter than "normal" ones (or vice versa). I cannot explain this phenomenon, but I think that it's just a sign of good code organization. In other words, whenever I see a situation when rules #1 and #2 are in conflict, I start looking for "code smells" and more often than not I do find some; and after refactoring - tada! no more painful choosing between rule #1 and rule #2, :-)
Finally, the rule #3 hase the smallest scope and therefore is the least critical.
Also, as mentined here by other colleagues, it is often very easy to "cheat" with this rule (for example, to write "if(disabled),,," instead of "if(!enabled)...").
I hope someone can make some sense of this opus...
As a general rule, if one is significantly larger than the other, I make the larger one the if block.
put the common path first
turn negative cheking into positive ones (!full == empty)
I always keep the most likely first.
In Perl I have an extra control structure to help with that. The inverse of if.
unless (alive) {
go_to_heaven;
} else {
say "MEDIC";
}
You should always put the most likely case first. Besides being more readable, it is faster. This also applies to switch statements.
I'm horrible when it comes to how I set up if statements. Basically, I set it up based on what exactly I'm looking for, which leads everything to be different.
if (userinput = null){
explodeViolently();
} else {
actually do stuff;
}
or perhaps something like
if (1+1=2) {
do stuff;
} else {
explodeViolently();
}
Which section of the if/else statement actually does things for me is a bad habit of mine.
I generally put the positive result (so the method) at the start so:
if(condition)
{
doSomething();
}
else
{
System.out.println("condition not true")
}
But if the condition has to be false for the method to be used, I would do this:
if(!condition)
{
doSomething();
}
else
{
System.out.println("condition true");
}
If you must have multiple exit points, put them first and make them clear:
if TerminatingCondition1 then
Exit
if TerminatingCondition2 then
Exit
Now we can progress with the usual stuff:
if NormalThing then
DoNormalThing
else
DoAbnormalThing

Resources