Is there a way in Stata to execute a piece of code if and only if a previous bit of code actually made changes?
For example, I am concatenating two variables only if one of them meets a regexm() test. I understand that if I run this qualifier as an if command, it only looks at the first observation. Is there a way to run an if command, say
if regexm(var`n', ".*\)$") {
// code
}
and have the if statement return true if the conditional is true for any observation, not just the first one?
For a match in any observation to trigger code, you need to count matches first:
count if regexm(var`n', ".*\)$")
if r(N) > 0 {
// code
}
if r(N) would suffice here, as non-zero arguments are treated as true and r(N) from count can never be negative.
Related
I'm doing a simple assignment where I have to go over test case coverage(statement coverage, path coverage, etc) of a function.
I've tried endlessly to add code here and StackOverflow won't accept it no matter how I format it, so I'll just explain a very simple example.
Let's say you get to an if statement that has a return statement inside it. In the line below the return line is the if's closing bracket '}'
My professor and our textbook have been pretty vague about what a statement is, but my understanding is that for a line of code to be a statement it has to perform some type of function such as assigning a value to a variable or being a conditional statement like an if or while loop.
So my questions are:
Does the closing bracket count as a statement? Or do they only count as a line?
When the computer is reading the code and hits the return statement, does it jump to the correct number of closing brackets before leaving the function and returning a value?
Closing brackets are not traditionally counted as statements.
Even if they follow a return (or any other kind of unconditional control transfer, e.g. goto to raise exception.).
A more interesting case is:
if (...) {
return;
x=1;
}
The x=1; statement can't get control. Test coverage should tell you it is uncovered because it never gets executed.
This example is exactly the same code, slightly reformatted:
if (...) {
return; x=1; }
Many test coverage tools will show you covered lines rather than covered code, so would mark the return line as covered. That's wrong; x=1; is still uncovered and the coverage display tool should make that clear.
This is especially important if you have a long source line which exits (e.g., by exception) in the middle:
x=foo().bar().baz();
If bar() throws an exception, then foo(). is covered, x=... is not, and baz() is not. This shows why line coverage, while common, can be very misleading.
Now consider this case:
if (a) {
...
if (b)
return;
}
c;
If a and b are true, the return statement executes. Control doesn't flow past the if (b) statement. If a is true and b is false... the return isn't executed and control flows past the if (b) to statement c;. In this case you can argue the } is "covered" even though it isn't a statement. A good coverage tool should show } c; as covered.
The problem here is that I do not understand well the difference between statements and blocks in control flow.
Looking the ternary operator I can use it to assign a variable. But this is an operator, so it is like applying a function--isn't it?
> my $variable = True ?? 34 !! 42;
34
since in the raku documentation says:
if documentation
if
To conditionally run a block of code, use an if followed by a
condition. The condition, an expression, will be evaluated immediately
after the statement before the if finishes. The block attached to the
condition will only be evaluated if the condition means True when
coerced to Bool. Unlike some languages the condition does not have to
be parenthesized, instead the { and } around the block are mandatory:
do documentation
do
The simplest way to run a block where it cannot be a stand-alone statement is by writing do before it:
so this should work in both cases:
> my $variable = do {34};
34
> my $variable = if True {34;} else {43;}
===SORRY!===
Word 'if' interpreted as a listop; please use 'do if' to introduce the statement control word
------> my $variable = if⏏ True {34;} else {43;}
Unexpected block in infix position (two terms in a row)
------> my $variable = if True⏏ {34;} else {43;}
as said in the error I need to add the do:
> my $variable = do if True {34;} else {43;}
34
So the if really does not run the block...or what is the real problem here?
TL;DR: The actual difference is between statement and expression, not statement and block. do is a statement prefix that creates expressions.
if actually creates a statement (anything that is run in Raku is), however, what it's not is an expression. do is a statement prefix, and what it does is turn statements into expressions.
However, if is not really a first-class function that you can assign to a variable or handle around. Whenever you find pieces of syntax such as that one (or for, for instance), you need to prefix them with do to "expressionify" them.
say &say.^name;# OUTPUT: «Sub» say &do.^name; # OUTPUT: «===SORRY!=== Error while compiling <tmp>Undeclared routine:...
say &if.^name; # OUTPUT: «===SORRY!=== Error while compiling <tmp>Undeclared routine: if used at line 1»
So if, by itself, does not create a block, it does not create an expression, it simply creates a statement. You need to precede it with do if you want it to actually turn it into a expression. It does run the block that's behind it, however.
Let's go back to the original question, statements and blocks. Blocks are objects, first-class citizens. You can use them, apply them, pass them around.
my &ifs = { if $_ {34} else {43}};
ifs(True).say; # OUTPUT: «34»
Statements are throwaway blocks you simply run. In some cases, they are also expressions: they yield a result which, then, you can assign.
my &ifs = { if $_ {34} else {43}};
my $result = ifs(True).say; # OUTPUT: «34»
say $result; # OUTPUT: «True»
The ifs(True).say statement prints to output, it also produces a result that can be assigned. All three lines are also statements, and as a matter of fact, expressions too.
Some control structures, however, do not create expressions.
Some others do; for creates a expression; while does not.
if is an example of this. They don't produce a result. You use them for the side effects: running a statement (if true) or another (if not). You might turn them into a block, as above, and pass them around. Or you can just precede them with do and make them produce a throwaway result, which you can then use.
So it will very much depend on your actual use case. You can surround the if statement with curly braces and create a block; or you can simply use the result creating an expression. Or you might want to use it just for the side effects, doing nothing.
I have a question related to a transition in my statechart (see image above). I have a variable called palletInUse which is a boolean-type and changes between true and false. For one transition in my statechart I want it to change when the variable palletInUse has the value true. I have tried it with for example:
palletInUse == true;
and also tried different code like, equals and contentEquals etc. but nothing seems to work. Do you have a solution for this, seemingly simple problem?
Thanks in advance
The condition is not monitored constantly, only when something is changed in the agent. When you assign a new value to variable with common "=" Java operator, it is not caught by the AnyLogic engine. You need to call onChange() function after that. Then, the transition should be executed.
There are other ways to trigger the condition check without explicit onChange() call. You may find them in AnyLogic Help article.
BTW, you may specify just boolean variable as the condition, it is not required to compare it with true or false:
palletInUse
The condition is not evaluated if nothing is happening, for that reason you have to make something happen constantly to have your condition evaluated. A typical way of doing is as you see in the following pictures:
Imagine you've got a while loop with an OR condition of two values. The second value has an increment (++). If the first value is true increment from the second value never seems to occur.
Let's take a look at a piece of code:
bool iterationPassed = false;
while (!iterationPassed || ++retries <= 3)
if(somethingHappened)
iterationPassed = true;
Okay, I'm very aware that this is logical. If the first value is true, there's an OR statement, why would there be a need to check the other value. But in this case, the other value is a result of another step (++) and that step never happened. So I guess incrementing or doing any sort of operation in a complex condition is a very bad practice? Also, is this language specific?
This should be a simple question on JasperReports. I'm trying to do a simple counter over the whole report that should increment based on a condition. However, whatever I try, it seems like the counter variable is always being incremented, regardless of the variable expression. My variable's definition properties are below:
Class: Integer
Calculation: Count
Reset type: Report
Increment type: None
Variable Expression: $F{on_target}.doubleValue() >= 0.0
Initial Value: Integer.valueOf(0)
I have a total of 23 rows in the data set, and based on the criteria, the counter should eventually equal 18. I have the variable outputting in the Summary band, with Evaluation Time to Now. However, regardless of the evaluation time, and even setting the Variable Expression to Boolean.valueOf(true == false), the variable's value always ends up as 23.
What simple little thing am I forgetting?
I think I've got it. This makes vaguely no sense, but... (mind you, this is my first time working with Jasper Variables, so it was trial and error).
The Variable Expression isn't quite a Boolean, where a counter type variable isn't incremented if the expression is false, like you'd think. The variable is incremented if there is any value evaluated in the expression. Thus, for me, what ended up working is below:
$F{on_target} >= 0 ? 1 : null
Note the usage of null if the expression should be false.
It makes vague, twisted sense. But is in no way intuitive. Oh well, so it goes...
or in other words:
When you are using the Calculation:Count function of a Jasper-defined Variable you want the Variable Expression to:
resolve to non-null value to increment the counter
resolve to a null value if you do not want to increment the counter
That's why the test listed above works
As well as the setting the variable expression to:
$F{on_target} >= 0 ? 1 : null
Try also setting the initialValueExpression of the variable to 0.
This worked for me:
$F{on_target} >= 0 ? 1 : BigDecimal.ZERO
No initial variable value necessary.