In Bash, Why `then` is needed in the conditional constructs? - bash

The conditional construct of if command looks like this:
if TEST-COMMANDS; then
CONSEQUENT-COMMANDS;
[elif MORE-TEST-COMMANDS; then
MORE-CONSEQUENTS;]
[else ALTERNATE-CONSEQUENTS;]
fi
And the loop construct of while command looks like this:
while TEST-COMMANDS; do CONSEQUENT-COMMANDS; done
I was wondering why then is needed in if command but not in while command? Why couldn't it be ommited?

do in the while syntax serves a similar purpose to then in the if syntax. They both signify the start of the body of the statement - differentiating it from the condition part of the statement.
The if conditional statement is a compound statement in the shell. The if & then sections of the statement are executed as two parts, the then section is only invoked if the if section ends with an exit status of 0. Both sections may contain multiple statements; therefore, a semi-colon alone is insufficient to separate these sections.

Like #shibley is saying in his answer, the do and then words are used to indicate the beginning of the block of actions to perform.
I have done some research and could not find the historical reasons, so I am going to guess the logical ones. It might be too subjective, so do not hesitate to comment your impressions below.
The bash syntax is quite "symmetrical": Whenever you have an case you finish it with esac. Also, it was designed in a very human way, so it is easily understandable.
That said, if you are in a while loop, it means that you are going to do something while a condition is true. Then, when it is not true anymore you are done.
However, in an if condition, you are saying that if something happens, then something needs to be executed.
In short: do and then are human-readable ways to indicate the same, that is, the beginning of a block of commands to be performed upon a while or if condition.

Related

Is it possible to have an 'IF' conditional statement nested within a 'CASE' conditional statement? (pseudocode)

I'm designing a pseudocode version of a programme thingy I made, in which one of the sections is someone inputting a number to select an option. When someone inputs a number, a value from a list is output. I thought using an 'IF' statement nested within a 'CASE' statement would make that task run more efficiently, but I'm not sure if that would still conform to the acceptable 'CASE' statement format. This is what I was envisioning for the first option:
**
CASE category OF
'1' : PRINT "Members who have chosen to work as volunteers,"
IF MemberInfo[2] = 'yes'
PRINT "MemberInfo[0], MemberInfo[1]"
**
The following numbers in the main 'CASE' statement would then follow the same format. Is this okay, or should I just make various 'IF' statements?
It does not makes to use CASE here as we use CASE when there are multiple options to choose from. Given its just one condition and action based on that an 'if' is more appropriate.
An if nested within CASE is not a good programming structure. Go with either CASE or IF.
Input a number as category
If category is a number
then
print list
end if
Sure, that makes sense. Real code can do it, so why not pseudocode?
(But if the other cases have the same format, there's probably a better way to do it: maybe a map lookup or using the category more dynamically, depending on what's changing between each case statement, and what stays the same.)

Have troubles with ocaml

I have some problems with OCAML I wrote this:
let visibility_graph observation memory =
Graph.add_node memory.graph observation.position
Graph.add_node memory.graph observation.spaseship;
but it's not working. However this is working:
let visibility_graph observation memory =
Graph.add_node memory.graph observation.position
You don't give enough information to give a full answer. However the code you show is completely consistent with your error reports. The first example appears to consist of two expressions (function calls) with no separator between them. To execute two expressions sequentially, you need a semicolon (;) between them.
The semicolon at the end of the first example appears to be misplaced. Things might work (depending on what the rest of your code looks like) if you just move this semicolon to the end of the previous line.
The second example looks like a ligitimate function defintion. Of course it's difficult to tell without knowing the definitions of all the identifiers used.

What is the colon before Fortran if `something:if(some_condition) then`?

I am working through some code other people have written and found a piece of Fortran syntax that I haven't seen yet and don't exactly understand nor can seem to find anything on the web about (probably because I don't know what it's called).
The code looks like this:
bisection_or_ordering:if(ordering /= 'bisection') then
...
do stuff
...
end if bisection_or_ordering
bisection_or_ordering is not a variable and not declared anywhere in the code.
What does this do? What is it for? And what is it called?
The part before the colon is a construct name.
Executable constructs with blocks - if, block, associate, critical, select case, select type and of course do - may optionally have these construct names.
They are useful both for identification (for clarity with nested or long constructs) but also for control under the exit statement (except to escape critical or do concurrent blocks).
The construct name may appear on the closing statement of the block, as in the question's example, but it is optional and must match if present.

Proper formatting for if statements inside loops

I'm curious which of the following is considered better form. My examples are snippets, but in more complex programs I've written, I can see arguments for and have used either.
Option 1: Skip ahead if a condition is met, otherwise execute lots of code:
for i in range(5):
if i == 3:
continue
print i
# and do lots of other stuff
The argument for this: clearly skips certain condition, doesn't result in overly nested code.
Option 2: Execute lots of code if condition is not met:
for i in range(5):
if i is not 3:
print i
# and do lots of other stuff
The argument for this: more verbose and doesn't use unnecessary continue.
(There seems to be a few questions related to this, but mostly about using functions or long blocks of code. I'm curious about the == vs != part.)
I think that, generally, Option 1 is better practice. In Option 2, 'lots of other stuff' is at a second level on indentation. Generally, the less indentation, the better.

Flowpattern doesn't exist

I have been working on a code in prolog for a while now and it is near compiling worthy and all my ideas seem to be solid so it should work when it compiles. It is a program that consults a database file for a list of clauses and then it awaits for a query by the user which it will then pick what information it needs from the sentence and query the database appropriately but there is a block of code that keeps giving me errors complaining that the flowpattern doesn't exist in the standard predicate this may be a silly question but even with all the looking into this I have done i can't find out how to fix this problem if someone could help me out or point me in the right direction that would be greatly appreciated.
Here is the block of code that gives the error:
loop(STR):-
scan(STR,LIST),
filter(LIST,LISroT1),
pars(LIST1,LIST2),
fail.
loop(STR):- STR >< "",readquery(L),loop(L).
readquery(QUERY):-nl,nl,write("Query: "),readln(QUERY).
scan(STR,[TOK|LIST]):-
fronttoken(STR,SYMB,STR1),!,
upper_lower(SYMB,TOK),
scan(STR1,LIST).
the specific line that the compiler complains about is fronttoken(STR,SYMB,STR),!,
any help will be apreaciated thanks!
Since we are looking at an "ex[c]er[p]t" of the code, it's hard to be sure what is going wrong, but the the given evidence points to this: loop/1 is being called before readquery/1 can do its work to populate (bind) the argument STR to loop/1.
Notice that loop/1 calls itself (recursively), and does so in a repeat/fail pattern. But the first time loop/1 runs, there's no indication in the code shown of how argument STR would get populated.
A clearer (more self-contained) code snippet would be like this:
loop :-
readquery(STR),
scan(STR,LIST),
filter(LIST,LISroT1),
pars(LIST1,LIST2),
fail.
loop :- loop.
This makes it clear that predicate loop doesn't actually return any result (and the given code snippet isn't complete enough to make clear what the program as a whole accomplishes). It assumes that the clauses ahead of fail in loop are deterministic, so that in failing, control passes through to the second (recursive) clause of loop/0. If this is not the case, the determinism could be forced by wrapping each call inside once/1.

Resources