Why Is Variable Declared Inside If Statement Created Even When Condition Evaluates to False

Why is variable declared inside IF statement created even when condition evaluates to false?

SQL Server does not have block level variable scoping.

It's per batch/stored proc etc

From MSDN (my bold)

The scope of a variable is the range
of Transact-SQL statements that can
reference the variable. The scope of a
variable lasts from the point it is
declared until the end of the batch or
stored procedure in which it is
declared.

why sometime variable are used as condition in if statement in javascript?

Here variable can be a boolean value or sometime to check variable existence you check it in if statement. Condition you might test with if statement.

  1. Element exist or not
  2. Input value empty or not
  3. collection length zero or greater

So following code:

if(result){
//do something
}

will cause false in the following condition(also called falsy):

  • false
  • 0 (zero)
  • "" (empty string)
  • null
  • undefined
  • NaN (a special Number value meaning Not-a-Number!)

Why can't we define a variable inside an if statement?

This is because section 8.5.1 of the C# language spec. states:

Furthermore, a variable initializer in a local variable declaration corresponds exactly to an assignment statement that is inserted immediately after the declaration.

This basically means that, when you do:

StringBuilder sb = new StringBuilder("test")

You're, in effect, doing the exact same thing as:

StringBuilder sb; sb = new StringBuilder("test")

As such, there is no longer a return value for your check against != null, as the assignment isn't a single expression, but rather a statement, which is a local-variable-declarator comprised of an identifier followed by an expression.

The language specification gives this example, stating that this:

void F() {
int x = 1, y, z = x * 2;
}

Is exactly equivalent to:

void F() {
int x; x = 1;
int y;
int z; z = x * 2;
}

C++, variable declaration in 'if' expression

As of C++17 what you were trying to do is finally possible:

if (int a = Func1(), b = Func2(); a && b)
{
// Do stuff with a and b.
}

Note the use of ; of instead of , to separate the declaration and the actual condition.

Why does non-equality check of one variable against many values always return true?

Use &&/AND/and, not ||/OR/or:

v != "x" && v != "y" && v != "z"

Problem

If an if block is always executed, the condition for the if block always evaluates to true. The logical expression must be wrong.

Let us consider v != "x" || v != "y" || v != "z" for each value of v.

  • When v = "x",

    v != "x" becomes "x" != "x", which is false.

    v != "y" becomes "x" != "y", which is true.

    v != "z" becomes "x" != "z", which is true.

    The expression evaluates to false || true || true, which is true.

  • When v = "y", the expression becomes

      "y" != "x" || "y" != "y" || "y" != "z"

    or true || false || true, which is true.

  • When v = "z", the expression becomes

      "z" != "x" || "z" != "y" || "z" != "z"

    or true || true || false, which is true.

  • For any other value for v, the expression evaluates to true || true || true, which is true.

Alternatively, consider the truth-table:

       │     A          B          C      │
v │ v != "x" v != "y" v != "z" │ A || B || C
───────┼──────────────────────────────────┼──────────────
"x" │ false true true │ true
"y" │ true false true │ true
"z" │ true true false │ true
other │ true true true │ true

As you can see, your logical expression always evaluates to true.

Solution

What you want to do is, find a logical expression that evaluates to true when

(v is not "x")and(v is not "y")and(v is not "z").

The correct construction is,

  • for C-like languages (eg. c#, javascript-(may need the strict equality operator !==), php)

      if (v != "x" && v != "y" && v != "z")
    {
    // the statements I want to be executed
    // if v is neither "x", nor "y", nor "z"
    }
  • for Pascal-like languages plsql

      IF (v != 'x' AND v != 'y' AND v != 'z') THEN
    -- the statements I want to be executed
    -- if v is neither "x", nor "y", nor "z"
    END IF;

De Morgan's law

By De Morgan's law, the expression can also be rewritten as (using C-like syntax)

!(v == "x" || v == "y" || v == "z")

meaning

not((v is "x")or(v is "y")or(v is "z")).

This makes the logic a bit more obvious.

Specific languages

Some languages have specific constructs for testing membership in sets, or you can use array/list operations.

  • sql: v NOT IN ('x', 'y', 'z')

  • javascript: ["x", "y", "z"].indexOf(v) == -1

  • python: v not in {"x", "y", "z"}

  • java: !Arrays.asList("x", "y", "z").contains(v)

  • java-9 (and above): !Set.of("x", "y", "z").contains(v)

R: IF statement evaluating expression despite condition being FALSE?

Solution

Adapting your example use:

testfun <- function(x,grids = NULL)
{
if(!is.null(grids)){
if(!all(expvarnames %in% names(grids))){
stop("Not all expvar column names found as column names in grids")
}
print(x+1)
}
}

Using this testfun(1) will return nothing. By specifying a default argument in the function as NULL the function then checks for this (i.e. no argument specified) and then doesn't continue the function if so.

The Reason the Problem Occurs

We go through each of the examples:

testfun <- function(x,grids)
{if(exists("grids")) globalgrids<<-grids
print(x+1)}

testfun(1) # Error in testfun(1) : argument "grids" is missing, with no default

Here we call the function testfun, giving only the x argument. testfun knows it needs two arguments, and so creates local variables x and grids. We have then given an argument to x and so it assigns the value to x. There is no argument to grids, however the variable has still been created, even though no value has been assigned to it. So grids exists, but has no value.

From this exists("grids") will be TRUE, but when we try to do globalgrids<<-grids we will get an error as grids has not been assigned a value, and so we can't assign anything to globalgrids.

testfun <- function(x,grids)
{if(exists("grids")) a<<-c(1,2,3)
print(x+1)}
testfun(1) #2 (and globally assigns a)

This, however is fine. grids exists as in the previous case, and we never actually try and access the value stored in grids, which would cause an error as we have not assigned one.

In the solution, we simply set a default value for grids, which means we can always get something whenever we try and access the variable. Unlike in the previous cases, we will get NULL, not that nothing is stored there.

The main point of this is that when you declare arguments in your function, they are created each time you use the function. They exist. However, if you don't assign them values in your function call then they will exist, but have no value. Then when you try and use them, their lack of values will throw an error.

Why can't variables be declared in an if statement?

Why? There can be no code path leading to the program assigning 1 to b without declaring it first.

You are right, but the compiler doesn't know that. The compiler does not execute the code. The compiler only translates to bytecode without evaluating expressions.

IF statement not raising error as expected

You need to declare your variable with a type before you can use it

declare @xyz int -- assuming the datatype of column riskgroup is also int

select @xyz = riskgroup
from polcont
where polcont = 555

EDIT

You altered your question since I have posted my answer, now your problem is you declare the variable in the wrong scope.

DECLARE @XYZ int

if @Ref = 0
begin
SELECT @XYZ = RISKGROUP
FROM POLCONT --WITH (NOLOCK, NOWAIT) don't do nolock everywhere !
WHERE CONT = 555
end

if @RISKGROUP <> @XYZ
begin
-- do something ...
end

EDIT 2

As to your question why it does not give any error, that is strange indeed

See this DBFiddle
I would indeed expect an error, but it somehow does not

This is explained in the documents as normal per design, though in my mind it is a flaw.

Also see this Question about the same subject

EDIT 3

So it seems that is does not matter much in TSQL where you declare your variables, but as a programmer I find this looking weird, so I prefer to put my variables in what is for me the correct scope.



Related Topics



Leave a reply



Submit