Jump to content
Sign in to follow this  
CarlGustaffa

Be careful about || (OR command), bites me every time

Recommended Posts

Although I am fully aware how the || (OR) command works, it manages to bite me in the ass somehow every time I try to "simplify" things by checking several things at once.

The following may appear obvious to some:

private ["_res"];
_aaa = true;
//_bbb = false; //yes, it's supposed to be commented out, that's the point.
sleep 0.1; //to illustrate it's not a delay problem.
if (_aaa || _bbb) then {
_res = true
} else {
_res = false
};
hint format ["%1", _res];

Since _aaa was set to true, wouldn't you expect the hint to show true? I know I would. But no, it decides that it is neither true or false, but instead undefined ("any"). Without as much as throwing an error message at me. If it for reasons I don't understand have to work like this, at least provide us with some input. Bug hunting such things can be a pain.

You know that one of them HAVE to be true, yet it just won't kick in, causing you to loose most hair in the process.

So, moral is never to use || command to try to simplify code and checks, unless you know exactly how it behaves.

Sorry for the rant. I'm hoping that typing this will make me never forget, although I know I will get into trouble again :p

Maybe that information should be shown on the biki for these logical commands?

Share this post


Link to post
Share on other sites

Ok, thing is:

OR is a logical operator, that receives two boolean statements A and B and returns true if at least one of them is true.

That means:

A or B => true

A or not B => true

not A or B => true

not A or not B => false

These are the four possibilities, not more, but also not less.

What you are trying to do is the following:

A or any.

And, what a surprise: "any" is NOT a boolean statement.

Edited by Bon

Share this post


Link to post
Share on other sites

Well no that's the way it is.

You are looking for "_bbb" which is commented out.

You can't work with variables which do not exist.

Same to every condition.

I was expecting if you have a "if" statement with multiple condition.

if ( (alive player) && (player in _vehicle) && (canMove _vehicle) ) then

Now it will check the whole condition even if the player is already dead.

I was thinking to reduce the engine load by writing logical conditions which will be cancelled after the most possible thing was happend. But they always run till the complete end even if some conditions already did not match.

What i wanna to tell you with this is:

Your condition will not stop after it has detected that "_aaa" was set to true.

It will finish reading the condition and then come to "_bbb" which do not exist. That's why your script fail.

Share this post


Link to post
Share on other sites

Could be due to _bbb being undefined. Any expression with undefined values will result in undefined answers ( aka "any" ).

Share this post


Link to post
Share on other sites

added -showScriptErrors to your command line?

Actually I think to remember that conditions are completely ignored when a variable isnt defined, and indeed throws no error at all :O

Edited by Sickboy

Share this post


Link to post
Share on other sites

Yeah, -showScriptErrors are added :) Yes Evil_Echo and SNKMAN, it does fail because _bbb is undefined, but I'd very much like to be informed about it. It is coding mistake, but I'm not given a clue about what is going on.

Flip about it: _aaa OR _bbb? If _aaa is true, it doesn't really matter what _bbb is, it doesn't make _aaa untrue, now does it? That's the slightly wrong way of thinking of it, which I'm trying to illustrate.

As I said, that was an obvious example, the problem comes when you're trying to check stuff directly without putting them into variables first. If you at the same time are confused about objNull, <null>, any, bool, isNil and isNull stuff - well, the new guy might be up for a challenge. Several times have I mistook <null> for objNull when I check the returns, and most likely someone new to scripting will too.

To illustrate:

_dada = nil; //Also try objNull and "".

hint format ["%1", (isNull _dada || isnil "_dada")];

Try guessing what comes out before hitting preview.

Naturally, for you coding gurus, all this is second nature and stupidly obvious. Was mostly addressing the new scripters on the {} :D

You can do a "superOR" operator now, but you have to use _check = (switch (true) do{}); where all cases are put under each case block, and finally defaults to false. But it's a bit messier than just doing the quick and dirty OR check.

Now, I'm really not against the need to initialize, it's just good practice. But when something goes wrong, I really want to know about it.

Share this post


Link to post
Share on other sites

It's an issue with the interpreter. It would be nice to have some tool to scan for undefined variables ( aka typos ), but have not heard of one yet. Perhaps someone could modify a version of splint to recognize sqf syntax.

In the meantime, it's use a console to track variables and program defensively. One thing that helps are some of the macros in CBA - ISNILS helps a lot.

Share this post


Link to post
Share on other sites

Here's a wrinkle to that. I have tried several ways to use an isNil check in the same conditional as another boolean. For instance:

if ((isNil "someVariable") || (someVariable < desiredAmount)) then
{
  *do magic stuff*
};

It doesn't register the conditional at all. If I do them separately, it worked, but not in the same conditional.

If someone has an example of a "nested" isNil like that, I'd love to see it. :) More likely, it is just bad coding on my part....

Share this post


Link to post
Share on other sites

Does that also happen when you're using global variables (booloeans) like: aaa bbb

instead of local ones?

I think when using it in a trigger's condition field with global variables and undefined

variable has been always seen as false by the game iirc.

~S~ CD

Share this post


Link to post
Share on other sites

It doesn't register the conditional at all. If I do them separately, it worked, but not in the same conditional.

Well, I'm pretty sure an undefined variable "breaks" the condition so it isn't further evaluated.

You could write yourself a function that could debug undefined vars:

_checkVar =
{
    if (isNil _this) exitWith
    {
         _error = "Undefined variable " + _this + "!";
         hint _error;
         diag_log text _error;
    };
    _return = compile str _this;
    _return
};


if ("_test" call _checkVar == "Something") then....

This is obviously an ugly way so I definitely wouldn't use it in anything official ;)

Share this post


Link to post
Share on other sites

2. _res variable doesn't exist outside if-else statement: http://community.bistudio.com/wiki/Variables#Scope You should "define" _res variable before if:

He did allready, private "_res"

Here is my solution to get rid of the problem :)

private "_res";
_aaa = true;
//_bbb = false; //yes, it's supposed to be commented out, that's the point.
sleep 0.1; //to illustrate it's not a delay problem.
if (_aaa || if (isNil "_bbb") then {false} else {_bbb}) then {
   _res = true
} else {
   _res = false
};
hint format ["%1", _res];

or

private "_res";
_aaa = true;
//_bbb = false; //yes, it's supposed to be commented out, that's the point.
sleep 0.1; //to illustrate it's not a delay problem.
_res = if (_aaa || if (isNil "_bbb") then {false} else {_bbb}) then {
   true
} else {
   false
};
hint format ["%1", _res];

Edit: Forgot to mention, it is not an or/|| problem. You could also do if (a_undefined_variable) then {} which would have the same result, nothing happens.

Xeno

Edited by Xeno

Share this post


Link to post
Share on other sites

Think we all can agree though that the main problem is that it doesn't throw a visible error, like "Error: Type ANY. Expected BOOL."

Share this post


Link to post
Share on other sites

@Xeno:

"Edit: Forgot to mention, it is not an or/|| problem. You could also do if (a_undefined_variable) then {} which would have the same result, nothing happens."

Yes, but I wouldn't expect it to either, because not being true or false wouldn't trigger then {} or else {} (well, actually, maybe the else{} part is easy to think would have been executed). But when one statement in a OR is true, it is easy to think that it will trigger. At least I do... Every time :D

Good suggestions though; how to handle possible nils in a nested conditional, debugging, and ACE function (wasn't aware of that one).

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×