Some time ago after not standing anymore lines like this:
if (arg)
invk(test);
else if (test)
{
alot();
stuff();
}
I decided for my self its better for readability in our 1920x1200 times, to not omit the {}.
So I wrote a tool that reformats my existing code.
later I noticed a bug in that tool resulting in
if (x)
{
...
}
else if(y)
{
...
}
else if(z)
{
...
}
had been changed (wihtout obvisiously changing the behavior) into:
if (x)
{
...
}
else
{
if(y)
{
...
}
else
{
if(z)
{
...
}
}
}
This made me realize (unintended) that this is actually what a else if does by syntax and semantical rules of C.
So is there even an statement like else if() existing or is it just an abuse of semantic that results in this usefull but (lets call it so for this purpose) obfuscation originated wording that breaks any formating rules and just serves as human readable?
As per the C11, chapter ยง6.8.4, selection statements, the available statement blocks are
if ( expression ) statement
if ( expression ) statement else statement
switch ( expression ) statement
and, regarding the else part,
An else is associated with the lexically nearest preceding if that is allowed by the
syntax.
So, there is no else if construct, exists as per standard C.
Obviously, an if (or if...else) block can exist as the statement in else block (nested if...else, we may say).
The choice of indentation , is left to the user.
Note:
Just to add, there is no reason for a separate else if construct to exist, the functionality can be achieved by nesting. See this wiki article. Relevant quote
The often-encountered else if in the C family of languages, and in COBOL and Haskell, is not a language feature but a set of nested and independent "if then else" statements combined with a particular source code layout. However, this also means that a distinct else-if construct is not really needed in these languages.
As every one is aware, there is several different styles of programming languages. The presence of a elseif is based on the style of language.
In a C/Pascal style the if statement is
if (...)
statment;
else
statement;
and you have a compound statement:
{
statment;
statment;
}
while in a Modula2 / VB / (python ?) style language you have
if (...)
statement;
...
statement;
else
statement;
...
statement;
end-if
in the Modula2 / VB you need a elseif statement because if you tried using else if you get
if (..)
else if (..)
else if (..)
end-if; end-if; end-if;
The end-if's at the end are rather ugly.
As #anatolyg noted this is why you have a #elif in C macro language.
Cobol-85 has a different take on the elseif statement. It provides an extended Select/case statement. In Cobol you have an evaluate:
evaluate option
when 1
...
when 2
...
but you can also do
evaluate true
when age > 21 and gender = 'male'
...
when age > 21 and gender = 'female'
In Cobol you can also mix the case and if structure
evaluate option also true
when 1 also age > 21 and gender = 'male'
....
when 1 also age > 21 and gender = 'female'
....
when 2 also any
....
One final point in java and C you sometimes see
if () {
} else if () {
} else if () {
}
To all intents and purposes, this is VB / Modula-2 written in Java/C.
Related
I can run a statement like
select 'a' like any('a',b'), but is it still possible to run this statement if ('a','b') were in an array?
select 'a' like any(array_construct('a','b')) doesn't work.
You can use a JavaScript UDF to approximate this behavior. Rather than trying to get JavaScript to simulate the like syntax, it's probably better to use richer, more expressive Regular Expressions. This UDF will return true if any array member matches that regexp pattern, false if none do, and null if the regex pattern is invalid or it encounters an unexpected error:
create or replace function LIKE_ANY_ARRAY("arr" array, "pattern" string)
returns boolean
language javascript
strict immutable
as
$$
"option strict"
try {
var regex = RegExp(pattern,"g")
for(let i=0; i<arr.length; i++) {
if(regex.test(arr[i])) return true;
}
return false;
} catch {
return null;
}
$$;
select like_any_array(array_construct('a','b'), 'a'); -- True
select like_any_array(array_construct('abcde','b'), '[a-z]{5}'); -- True
select like_any_array(array_construct('abcde','b'), '[a-z]{8}'); -- False, none have enough letters
select like_any_array(array_construct(2,'b'), '[a-z]{8}'); -- Auto-casting
select like_any_array(array_construct('a', 'b'), '['); -- Invalid regex pattern returns NULL
This is returning a Boolean to approximate the behavior of the LIKE ANY function, but could very easily be converted to returning an array of all the matching members or an integer representing the first match, etc.
You could turn you array into a string that resembles a regex and match against that
where 'a' rlike array_to_string( ['a','b'],'|')
Can anyone help me with the following task:
Create a procedure SectionCount(instructor_ID) that, according to the instructor's ID, displays the numbers of those of its sections with the largest number of students enrolled. Display appropriate messages if an instructor with such an ID does not exist or if there are no sections to lead. Add a block to handle the necessary exceptions.
my solution is the following..whether it is correct:
CREATE OR REPLACE FUNCTION your_function_name(i_student_id NUMBER)
RETURN NUMBER AS v_sections_count NUMBER;
BEGIN
SELECT COUNT(SECTION_ID) into v_sections_count FROM ENROLLMENT WHERE STUDENT_ID = i_student_id;
IF v_sections_count > 3 THEN
RETURN -1;
ELSE
RETURN v_sections_count;
END IF;
EXCEPTION WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('An error occured.');
RETURN -2;
END;
A suggestion or two, if I may.
always use table's alias when referencing columns. In your case, that's only one table but - often you have to "fix" a query and add yet another table, and then you don't know which column belongs to which table and have to add aliases anyway.
try to use only one RETURN per function (two, if there's an exception handling section - as in your function) because you might do something wrong in code logic and RETURN (i.e. terminate further execution) although you didn't actually want to do that. Instead, add a new variable which will be used to "calculate" the return value (such as retval in code I posted); then return its value
DBMS_OUTPUT.PUT_LINE is OK for debugging; nobody else will ever see it, because end users won't call that function from SQL*Plus (or other tools which are capable of displaying that message). For example, it (DBMS_OUTPUT.PUT_LINE) won't raise error in Oracle Apex or Oracle Forms, but you won't see anything.
Also, add SQLERRM which will actually show you which error happened. Info "an error occurred" isn't very descriptive
So:
CREATE OR REPLACE FUNCTION your_function_name (i_student_id NUMBER)
RETURN NUMBER
AS
v_sections_count NUMBER;
retval NUMBER;
BEGIN
SELECT COUNT(e.section_id)
INTO v_sections_count
FROM enrollment e
WHERE e.student_id = i_student_id;
retval := CASE WHEN v_sections_count > 3 then -1
ELSE v_sections_count
END;
RETURN retval;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('An error occured: ' || SQLERRM);
retval := -2;
RETURN retval;
END your_function_name ;
I have a simple online interface for writing Groovy scripts that get incorporated into a larger piece of software. I was bouncing between on project in VB6 and the other in Groovy and so accidentally used one equals sign (which VB6 does for if statements) where I meant to use a double-equals in Groovy.
Could assigning a value to a database field in an if statement in this fashion actually update all of the records for which the rest of the if conditions were true?
Java's assignment operator will return the variable just assigned. If this is inside a statement expecting a boolean it will be evaluated according to Groovy's truthiness. We can see this in the Groovy console with some asserts:
groovy:000> assert (foo = 1)
===> null
groovy:000> assert (foo = 0)
ERROR org.codehaus.groovy.runtime.powerassert.PowerAssertionError:
assert (foo = 0)
|
0
or with an if statement:
groovy:000> if ((foo = 'bar')) {
groovy:001> println "Assignment was true!"
groovy:002> }
Assignment was true!
Note that you need the double parentheses for this to "work" because without them you will get a compile error trying to parse it:
groovy:000> if (foo = 'bar') {
groovy:001> println "Assignment was true!"
groovysh_parse: 2: expecting ')', found '=' # line 2, column 9.
if (foo = 'bar') {
^
It can be pretty insidious. It has some use cases though, like a while loop that iterates on a method's return value until it returns false:
while (data = getData()) {
doWork(data)
}
println "Done with all the data"
Can I set condition on language such as:
IF(statement is in Hebrew)
.....
ELSE IF(statement in English)
......
ELSE
......
Or is there other way to achieve the same result?
SQL Server doesn't have any built-in functions for determining what language a string is in.
If you choose to write your own function, then employing it in the IF structure you want is simple:
IF dbo.GetLanguage(statement) = 'Hebrew'
...
ELSE IF dbo.GetLanguage(statement) = 'English'
...
ELSE
Can someone please help me understand how to code lex and yacc file for a C program to parse goto and blocks(labels).
Here is some example I found on the net:
<statement> ::=
<variable> <inc> <semi>
| <variable> <assign> <null> <semi>
| <goto> <label> <semi>
But how to uniquely identify label. Can someone give me an example of this or any link where it is mentioned.
<label> here really means a symbol - an identifier - which must correspond to a label definition somewhere else for the program to be correct.
You don't need to "uniquely identify" as part of the parser, a label is identified by the syntax of the language. It is entirely legal to allow labels to overlap with other symbol / variable names. Just add a rule for a legal label, reuse the lexer TOKEN for IDENTIFIER, then store labels in a symbol table per function so you can detect duplicate labels.
Typically in C-like languages, a label is part of a statement rule. It doesn't usually make sense anywhere else. The way I do it:
labeled_statement:
IDENTIFIER ':' statement
{
$$ = $3;
$$->label = new Label($1);
}
;
Another way:
label:
IDENTIFIER ':'
{ $$ = new Label($1); }
;
labeled_statement:
label statement
{
$$ = $2;
$$->label = $1;
}
;