spring expression not evaluating simple relational operator - spring-el

Why is the following code returning TRUE when it is obviously not TRUE?
ExpressionParser parser = new SpelExpressionParser();
Integer s = new Integer(132);
EvaluationContext context = new StandardEvaluationContext();
context.setVariable("rpaCount", s);
Expression exp = parser.parseExpression("#rpaCount>1000");
Boolean truth = (Boolean)exp.getValue();
System.out.println(truth); // returning TRUE ....HOW is 132 > 1000?

It seems the context is null and is why the expression is not getting evaluated correctly. I fully did not understand the usage of EvaluationContext and hence the confusion. Closing the question after clarifying the usage of EvaluationContext.

Related

Can we assign a value inside the if statement?

#include <stdio.h>
void main()
{
int x = 0;
if (x = 0)
printf("It's zero\n");
else
printf("It's not zero\n");
}
Why is the statement if (x = 0) not an error? Can we assign a value like that in an if statement? Why is it not generating an error, and why is the else statement getting executed?
Yes, it is allowed to assign the value inside the if statement. This is very handy, among other things, when you want to call the function and check it's return for error:
int rc;
if ((rc = check())) {
// here rc is non-zero, often an indication of a failure
}
Note how I've put an extra pair of parenthesis around my assignment - since it is such an omnipresent source of confusion, compilers are usually warning about assignement in the if block, assuming you might have made a typo. Extra pair of parenthesis makes it clear for compiler that this is what I intended.
By the way, there is no special exception crafted here, validity of this syntax stems from general C grammar - an assignment operator evaluates to assigned value.
Yes, this is a perfectly valid syntax, there is no reason to disallow this.
Quoting C11,
[...] An
assignment expression has the value of the left operand after the assignment. [...]
So, the value which is stored in the LHS operand, would be used for the if statement condition evaluation.
In your case, the variable x holds the value 0 after the assignment, and if (0) is FALSY, that's why the else block gets executed.
However, most of the time, this syntax is used wrongly, instead of the comparison. That's why most of the compilers emit a warning message on this construct.
warning: suggest parentheses around assignment used as truth value [-Wparentheses]
if (x = 0)
^
If you're sure what you're doing, you can wrap the if condition with an assignment expression in an additional pair of parenthesis, and you'll be good to go.
In C, the only requirement for an if statement is that it contains an expression. The truth of the statement is based on whether or not the expression evaluates to zero.
The assignment operator also evaluates to the assigned value, so if(a = 0) would be false, whereas if(a = x) where x != 0 would be true.
Since the assignment operator is an expression, it is acceptable to place in an if statement, though a frequent beginner mistake is to use the assignment operator where they intended to use the equality test operator ==.
One way you can avoid this is mistake is, if either side of the comparison is an r-value, put that on the left, so that if you ever accidentally use = where you meant ==, you will get a compilation error. Compare:
if(p = NULL) // Valid syntax
...
if(NULL = p) // Syntax error
...

Unknown behaviour of assignment op in C [duplicate]

This question already has answers here:
Using assignment as a condition expression?
(5 answers)
Closed 4 years ago.
I don't know exactly cases of true and false returning from this construction. Can you describe it? Sry, if it is in a google search, I have not found.
( (struct->param = param_init()) == NULL )
param_init() this statement will be evaluated first and output will be stored in struct->param.
if struct->param contains NULL, if conditional will be evaluated to true
or if struct->param contains non NULL, if conditional will be evaluated to false.
if ( (struct1->param = param_init()) == NULL )
is an obfuscated way of writing
struct1->param = param_init();
if(struct1->param == NULL)
{
...
}
Use the latter form, assignment inside conditions should be avoided.
As assignment operator is having lowest priority that's why it always executes at last ,so in first Parentheses the function param_init() will get call first and the return value of this function will get assigned to structure pointer struct->param and at last value of struct->param will get compared with 0(NULL) and result(either 0 or 1) will return .
NOTE : Removal of Parentheses will change the result as it changes the precedence .

Precedence of arr[x++]--

I am confused on how to parse precedence of operations in C. the line
countArray[*string++]--
Is executing how I want it to, but I don't understand the steps that result in countArray[*string]-- being evaluated before *string++.
My research on C precedence and binding didn't provide answers that relate to this case, and I'm wondering about general rules for post/pre-increment and post/pre-decrement when in combination with other post/pre - crements.
How does C know to evaluate it this way?
void discountChars(char* string, char** countArray)
{
int test;
while(*string) {
test = *string;
//why is countArray[*string]-- evaluated before string++ is incremented?
countArray[*string++]--;
printf("countArray[%d] = %d\n", test, countArray[test]);
}
}
You can break this:
countArray[*string++]--;
down into this:
char index = *string; // get char from `string` into temporary index
string++; // increment `string`
countArray[index]--; // decrement `countArray` value at given index
and then it should be clearer what's going on.
As it has been stated many times, precedence has no connection to the order of evaluation. The only thing in C language that can affect order of evaluation is sequencing. Precedence has nothing to do with it.
It is also unclear where you got the strange idea that "countArray[*string]-- is being evaluated before *string++". This is simply impossible. The expression in [] will always be evaluated first, since its result is required to perform the element access (i.e. sequenced before the element access). Which means that the opposite is true: *string++ is evaluated before countArray[*string]--.
So, the sequence of steps here is
Evaluate *string++. The result of this expression is the original value of *string. Let's designate it tmp.
This expression also "schedules" a side-effect - increment of string. But this increment does not have to happen right now.
Evaluate countArray[tmp]--. The result of this expression is the original value of countArray[tmp]. This result is immediately discareded.
This expression also "schedules" a side-effect - decrement of countArray[tmp]. But this decrement does not have to happen right now.
Complete the evaluation of the full expression . If any of the above side-effects are still pending, complete them right now.
For example, one possible evaluation schedule might look as follows
char tmp = *string; // subexpression inside `[]`
countArray[tmp]; // full expression, result discarded
countArray[tmp] = countArray[tmp] - 1; // side-effect
string = string + 1; // side-effect
Another possible evaluation schedule is
char tmp = *string; // subexpression inside `[]`
string = string + 1; // side-effect
countArray[tmp]; // full expression, result discarded
countArray[tmp] = countArray[tmp] - 1; // side-effect
It can even be evaluated as
string = string + 1; // side-effect
char tmp = *(string - 1); // subexpression inside `[]`
countArray[tmp]; // full expression, result discarded
countArray[tmp] = countArray[tmp] - 1; // side-effect
Precedence controls groupings of operators and operands, not order of evaluation.
The expression *string++ must be evaluated before it can be used as an array subscript; however, the side effect of updating string may happen after the larger expression has been evaluated. The following sequence of events is allowed:
t1 <- *string
countArray[t1] <- countArray[t1] - 1
string <- string + 1
Then again, so is the following:
t1 <- *string
string <- string + 1
countArray[t1] <- countArray[t1] - 1

Compound statement to change value after returning it?

Im wondering if it is possible to have a variable changed after returning its value?
The function in question is a simple get function for a private Boolean flag variable. I would like reads of this flag to be destructive, so I thought:
bool myGet (context_t * someContext) {
return (someContext->flag) ? (someContext->flag = false) : false;
}
Reasoning that the result of evaluating the statement (someContext->flag = false)would be true, but it appears not.
Maybe it's evaluated before the condition (someContext->flag)?.
Is there any other way to achieve the intended functionality without resorting to temporarily storing the flag value, clearing the flag and then returning the temporary copy? Thanks.
All of the argument to return must be evaluated before the return itself is evaluated, i.e. before execution leaves the current function.
The value of an assignment is the assigned value, so it's false as you experienced.
I think the closest you can come is with post-increment, but that will of course strictly limit the values available.
There's nothing wrong with doing it the explicit way:
bool getAndClear(context_t *someContext)
{
if(someContext->flag)
{
someContext->flag = false;
return true;
}
return false;
}
it's very clear and way easier to understand than your scary code. It's easy to imagine that it's possible for compiler to optimize it, since it's pretty straight-forward.
If I wanted to get clever, I'd probably use something like:
bool getAndClear2(context_t *someContext)
{
const bool flag = someContext->flag;
someContext->flag ^= flag; /* Clears if set, leaves alone if not set. */
return flag;
}
Note that it doesn't branch, which is sometimes nifty. But, again, being clever is not always the most awesome path to take.
Also note that I consider it a requirement that this function isn't just named "get" something, since it doesn't take a const pointer that would be an instant warning flag in my head. Since it has super-strange (for a getter) side-effects, that should be reflected in the name somehow.
Reasoning that the result of evaluating the statement (someContext->flag = false) would be true, but it appears not.
(someContext->flag = false) is an assignment expression. Its value is the value of the expression being assigned (i.e. false).
The assignment does go through, although it happens before the return, not after it. If you want to be fancy and stay with the ternary operator, you can use comma operator, like this:
return (someContext->flag) ? (someContext->flag = false, true) : false;
This is not very readable, though, so I would prefer this equivalent implementation, which has no conditionals:
bool temp = someContext->flag;
someContext->flag = false;
return temp;
When you do (someContext->flag = false) it set someContext->flag to false, then return it.
You could do :
return (someContext->flag) ? !(someContext->flag = false) : false;
This way you will return the oposite of someContext->flag that you just set to false (so you return true) but someContext->flag will stay false after the return
EDIT
the most unreadable would be :
return !(someContext->flag = !someContext->flag);
You can use the post-decrement operator:
return (someContext->flag) ? someContext->flag-- : false;
This will only have the desired result if the true value for your flag has the numeric value 1.

lvalue required as left operand of assignment

Why am I getting
lvalue required as left operand of assignment
with a single string comparison? How can I fix this in C?
if (strcmp("hello", "hello") = 0)
Thanks!
You need to compare, not assign:
if (strcmp("hello", "hello") == 0)
^
Because you want to check if the result of strcmp("hello", "hello") equals to 0.
About the error:
lvalue required as left operand of
assignment
lvalue means an assignable value (variable), and in assignment the left value to the = has to be lvalue (pretty clear).
Both function results and constants are not assignable (rvalues), so they are rvalues. so the order doesn't matter and if you forget to use == you will get this error. (edit:)I consider it a good practice in comparison to put the constant in the left side, so if you write = instead of ==, you will get a compilation error. for example:
int a = 5;
if (a = 0) // Always evaluated as false, no error.
{
//...
}
vs.
int a = 5;
if (0 = a) // Generates compilation error, you cannot assign a to 0 (rvalue)
{
//...
}
(see first answer to this question: https://stackoverflow.com/questions/2349378/new-programming-jargon-you-coined)
You cannot assign an rvalue to an rvalue.
if (strcmp("hello", "hello") = 0)
is wrong. Suggestions:
if (strcmp("hello", "hello") == 0)
^
= is the assign operator.
== is the equal to operator.
I know many new programmers are confused with this fact.
Change = to ==
i.e
if (strcmp("hello", "hello") == 0)
You want to compare the result of strcmp() to 0. So you need ==. Assigning it to 0 won't work because rvalues cannot be assigned to.
You are trying to assign a value to a function, which is not possible in C. Try the comparison operator instead:
if (strcmp("hello", "hello") == 0)
I found that an answer to this issue when dealing with math is that the operator on the left hand side must be the variable you are trying to change. The logic cannot come first.
coin1 + coin2 + coin3 = coinTotal; // Wrong
coinTotal = coin1 + coin2 + coin3; // Right
This isn't a direct answer to your question but it might be helpful to future people who google the same thing I googled.
if (strcmp("hello", "hello") = 0)
Is trying to assign 0 to function return value which isn't lvalue.
Function return values are not lvalue (no storage for it), so any attempt to assign value to something that is not lvalue result in error.
Best practice to avoid such mistakes in if conditions is to use constant value on left side of comparison, so even if you use "=" instead "==", constant being not lvalue will immediately give error and avoid accidental value assignment and causing false positive if condition.

Resources