Jump to content
lordprimate

A Question about Lazy Evaluation

Recommended Posts

Hello All, I guess this is a post for Dev's or those with experience with lazy eval.

my question is this:

In what circumstances does lazy eval. work?

for example:

i know it works inside of "if" statement, however, what of "while" or "waitUntil"? or any other place you can use "&&" or "and"?

is there a Wiki page i didnt find, i did search, however, did not find anything relating to my question.

Share this post


Link to post
Share on other sites

Hey Lordprimate!

I took a look at the biki (you've probably been there already but I'll link it for the halibut) and it does seem to be a feature inherent to && and ||, not so much to a specific command like waitUntil or what have you.

Hope that helps!

Edit: Also this link here might be of some use to you.

Edited by Adombom
infoz

Share this post


Link to post
Share on other sites

From my (limited) understanding you should be able to use lazy evaluation in any condition aslong as it is && / and and isn't || / or. It will make sure the preceeding condition is true before evaluation of the next condition. In the case of using || / or it wouldn't make much sense (in my way of thinking :p) to use lazy evaluation because you could need ANY of the conditions there to be true at any given time, thus you need to evaluate all of them, every time.

I always use

waitUntil { ((someCondition) && {someCondition2} && {someCondition3}) };

All's I can say, it appears to work just fine. As I said, I've limited knowledge though so who knows. I learned from the BI wiki IF example, and put it to use with other control structures. My 2c.

regards,

Iceman77

Edited by Iceman77

Share this post


Link to post
Share on other sites

Hmmm interesting. I agree with Iceman that using lazy eval for OR does not make sense. I have no knowledge from experimentation but i have been using it slightly different to Iceman e.g

waitUntil { ( (someCondition) && { someCondition2 && { someCondition3 } } ) };

So if someCondition is true then evaluate { someCondition2 && {someCondition3} }

if someCondition2 is true then evaluate { someCondition3 }

As i said i have no proof that this is correct, it is just what made logical sense to me. A cascade of code blocks.

Share this post


Link to post
Share on other sites

yea i wasnt really thinking about the || / or i just typed it.. please distreguard that part.. so from what you are saying, in your experience, lazy eval can be used in any of those conditions (if, while, waitUntil). Thats good info to know!

Thank You!

LP

Share this post


Link to post
Share on other sites
In the case of using || / or it wouldn't make much sense (in my way of thinking :p) to use lazy evaluation because you could need ANY of the conditions there to be true at any given time, thus you need to evaluate all of them, every time.

Thats not correct.

Lazy evaluation skips all statements after an "or" if the preceding Condition is TRUE (and exits with TRUE)

Lazy evaluation skips all statements after an "and" if the preceding Condition is FALSE (and exits with FALSE)

Why?:

OR:

a//b//a||b

0//0//0

0//1//1

1//0//1

1//1//1

No matter what if one Condition is true the whole Condition is true

AND:

a//b//a&&b

0//0//0

0//1//0

1//0//0

1//1//1

No matter what if one Condition is false the whole Condition is false

How to use it in sqf?

if (condition1 || {condition2} || {condition3}) then {}; // condition3 is only evaluated if condition1 and condition2 are false
if (condition1 && {condition2} && {condition3}) then {}; // condition3 is only evaluated if condition1 and condition2 are true

  • Like 1

Share this post


Link to post
Share on other sites
Lazy evaluation skips all statements after an "or" if the preceding Condition is TRUE (and exits with TRUE)

Of course doh, makes sense, thanks for the correction.

Share this post


Link to post
Share on other sites

if (condition1 || {condition2} || {condition3}) then {}; // condition3 is only evaluated if condition1 and condition2 are false

Oh okay. That's useful to know. Thanks :icon_razz:

Share this post


Link to post
Share on other sites

Hello,sorry for the dumb question, but I'm having some trouble with conditionals in my scripts and maybe here is the key.

Why you use brackets {} inside some conditions and parenthesis () in other's?? I mean, if do this, I would type: waitUntil { ( (someCondition) && ( someCondition2 && ( someCondition3 ) ) ) }; instead of waitUntil { ( (someCondition) && { someCondition2 && { someCondition3 } } ) };

Can you explain? In the comref, the while or waituntil commands doesen't say anything. Thanks in advance.

Share this post


Link to post
Share on other sites

() is just for grouping

{} utilises the advantages of Lazy evaluation (see my post above for more infos)

Share this post


Link to post
Share on other sites

One more question about the brackets. Is there a difference between

if (condition1 && {condition2} & {condition3}) then {};

and

if (condition1 && {condition2 & {condition3}}) then {};

Share this post


Link to post
Share on other sites

I'll test it...

Testresults:

TEST #1 (Condition2 and Condition3 false)

My Code:

number_1 = 1;
number_2 = 2;
number_3 = 3;

TRN_fnc_test1 = {

if ((number_1 == 1) && {number_2 == 4} && {number_3 == 4}) then {};

};

TRN_fnc_test2 = {

if ((number_1 == 1) && {(number_2 == 4) && {number_3 == 4}}) then {};

};

Result:

TRN_fnc_test1 0.000900269 ms

TRN_fnc_test1 0.000799561 ms

TEST #2 (Condition2 false)

My Code:

number_1 = 1;
number_2 = 2;
number_3 = 3;

TRN_fnc_test1 = {

if ((number_1 == 1) && {number_2 == 2} && {number_3 == 4}) then {};

};

TRN_fnc_test2 = {

if ((number_1 == 1) && {(number_2 == 2) && {number_3 == 4}}) then {};

};

Result:

TRN_fnc_test1 0.000799561 ms

TRN_fnc_test1 0.000897217 ms

TEST #3 (Condition1 and Condition2 false)

My Code:

number_1 = 1;
number_2 = 2;
number_3 = 3;

TRN_fnc_test1 = {

if ((number_1 == 4) && {number_2 == 2} && {number_3 == 3}) then {};

};

TRN_fnc_test2 = {

if ((number_1 == 4) && {(number_2 == 2) && {number_3 == 3}}) then {};

};

Result:

TRN_fnc_test1 0.000897217 ms

TRN_fnc_test1 0.000799561 ms

TEST #4 (Condition1 false)

My Code:

number_1 = 1;
number_2 = 2;
number_3 = 3;

TRN_fnc_test1 = {

if ((number_1 == 4) && {number_2 == 4} && {number_3 == 3}) then {};

};

TRN_fnc_test2 = {

if ((number_1 == 4) && {(number_2 == 4) && {number_3 == 3}}) then {};

};

Result:

TRN_fnc_test1 0.000793457 ms

TRN_fnc_test1 0.000805664 ms

Edited by trnapster
  • Like 1

Share this post


Link to post
Share on other sites
Why you use brackets {} inside some conditions and parenthesis () in other's??

Normal parenthesis () are used for precedence e.g

2+3*8 = 48

48 as generally * has a higher precedence than +

So if you wanted 2+3 then multiplied by 8 you would write it as

(2+3)*8

It makes sure the 2+3 is done first before it is multiplied by 8

The other braces {} , curly braces or as this is ARMA code braces

In the instances we are talking about above (conditionals) they are being used for Lazy Evaluation (see example 2 on this page)

For example say we had

_myVar = nil;
if ( _myVar > 5 ) then {

This would fail with an error, as _myVar is nil (non existant) trying to check it would result in a Undefined variable error.

_myVar = nil;
if ( !(isNil "_myVar") && _myVar > 5 ) then {

This would also fail, it would check whether _myVar is nil but still continue on with the next to see if _myVar is greater than 5.

but

_myVar = nil;
if ( !(isNil "_myVar") && { _myVar > 5 } ) then {

If _myVar is NOT nil , then and only then go on to check whether _myVar is greater than 5 (the condition between {} ).

If _myVar is nil then the part in {} will not be evaluated.

Hope that makes sense

Share this post


Link to post
Share on other sites

In fact, in c programming conditions are always evaluated in the lazy method, so if you want function calls and the likes in a condition to get executed you need to think carefully. In ArmA you have to specifically mention you want lazy evaluation, I guess to make such mistakes less obvious.

If a function does something important rather than just do a quick value return, it's probably best to call it before the if condition anyway just to keep things more organized.

Share this post


Link to post
Share on other sites
In fact, in c programming conditions are always evaluated in the lazy method, so if you want function calls and the likes in a condition to get executed you need to think carefully. In ArmA you have to specifically mention you want lazy evaluation, I guess to make such mistakes less obvious.

If a function does something important rather than just do a quick value return, it's probably best to call it before the if condition anyway just to keep things more organized.

C does not have lazy evaluation of if statements. Instead it's "short-circuit" evaluation.

With lazy evaluation the value of a an expression is evaluated only when it's needed. Whereas short-circuited evaluation means that evaluation of the expression stops when the runtime knows the answer. For example the case of having && operator, the runtime immediately knows the value of the expression if the left hand side evaluates to false. Or with || (or) if the left hand side evaluates to true, then the runtime knows the value to be true and it stops evaluating rest of the statement.

http://en.wikipedia.org/wiki/Short-circuit_evaluation

Also, the terminology on Biki is wrong. It should say short-circuited evaluation, not lazy.

Edited by Xendance

Share this post


Link to post
Share on other sites

Ah, well, I was using the same terminology used in this thread to not confuse the OP. But I guess it ended up confusing anyway :)

But yes, "lazy" evaluation is something completely different to both if conditions in ArmA and c.

Share this post


Link to post
Share on other sites

// thread revival!

 

Can I use lazy evaluation as a safer way of checking potentially undefined variables?

 

if (_defdvar1 and _maybeundefd1) then {do some stuff}

Is risky. Regardless of what _defdvar1 is, defined, undefined or whatever, I'll get an error. So in the past, I've done

 

if (_defdvar1) then {if (_maybeundef1)} then {do some stuff}; 

Is safer. But is lazy evaluation (yes, I've read KZKs stuff on this) another, more desirable way of doing this?

 

if (_defdvar1 and {_maybeundef1}) then {do stuff}

Will this break if _defdvar is false and _maybeundef1 is undefined?

Share this post


Link to post
Share on other sites
21 minutes ago, Tankbuster said:

// thread revival!

 

Can I use lazy evaluation as a safer way of checking potentially undefined variables?

 


if (_defdvar1 and _maybeundefd1) then {do some stuff}

Is risky. Regardless of what _defdvar1 is, defined, undefined or whatever, I'll get an error. So in the past, I've done

 


if (_defdvar1) then {if (_maybeundef1)} then {do some stuff}; 

Is safer. But is lazy evaluation (yes, I've read KZKs stuff on this) another, more desirable way of doing this?

 


if (_defdvar1 and {_maybeundef1}) then {do stuff}

Will this break if _defdvar is false and _maybeundef1 is undefined?

 

I'd just use params instead.

 

Cheers

Share this post


Link to post
Share on other sites

params? For this sort of thing? Pray, tell me more. :)

Share this post


Link to post
Share on other sites

Yes you can. The terms in lazy evaluation are skipped if anything failed before.

if (!isNil "myVariable" && {myvariable == value}) then {...}; will not failed in case of myVariable still undefined.

if (!isNil "myVariable" && myvariable == value) then {...}; // error undefined variable.

 

 

  • Like 1

Share this post


Link to post
Share on other sites
8 hours ago, Tankbuster said:

 


if (_defdvar1 and {_maybeundef1}) then {do stuff}

Will this break if _defdvar is false and _maybeundef1 is undefined?

Undefined variable in code clock does not cause error, it cause return of nil. Which in turn causes if to stop evaluating condition and neither then-statement nor else-statement is executed.

Code blocks can't be the first in if condition though and must evaluate to boolean type or nil; nil or boolean value can be placed the last to ensure that.

So you can get this combination working if maybeundef1 and maybeundef2 represent boolean types if defined:

if (true && {maybeundef1} && {maybeundef2} && {some code returning nil or boolean} && {finally do some stuff; nil});

 

Share this post


Link to post
Share on other sites

Ah! Code block can't be first, hence if true and {~~~}.

Excellent, thank you!

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

×