Nelis75733126/Sandbox – User

From Bohemia Interactive Community
Jump to navigation Jump to search
m (line breaks.)
m (Lou Montana moved page User:Nelis.75733126/Sandbox to User:Nelis75733126/Sandbox: Automatically moved page while renaming the user "Nelis.75733126" to "Nelis75733126")
 
(3 intermediate revisions by one other user not shown)
Line 1: Line 1:
== About writing SQF code without negation ==
{{ Feature | Informative |
'''Important note from the author'''
This page is about a '''subjective''' topic. This article was written by someone who is a proponent of avoiding negation entirely.<br>
The author of this article wants to make it 100% clear that code written '''with negation is functional and capable of getting results'''.<br>
Like every other language, they can be written in multiple styles. One of which is using negation. Another can be to write without negation. It all comes down to subjective preferences.}}
=== What is "negation"? ===
Negation refers to formulating a sentence in a negative way. Here are some examples:
* "do NOT do that!"
* "do NOT change that thing!"
* "he is NOT happy!"
Simply put: any sentence with the word "NOT" in it is using negation.


=== Why care about negation? ===
Research has shown ( look it up if you wish ) that the human brain has more difficulty processing sentences with negation in it. Which could lead to the need for reading a sentence multiple times.<br>
The same goes for code in any language.
=== [[exitWith]] is your friend :) ===
To show you why, here is an example of how something could be written '''with''' negation, followed by code '''without''' negation that does exactly the same thing.
<sqf>
/*
  with negation, basic checks on params.
  a typical "only continue if all parameters meet the required conditions"
*/
[ controlNull, objNull, 0, true ] call {
  if( !isNull( _this select 0 ) ) then {
      if( !isNull( _this select 1 ) ) then {
        if( !isNil{ _this select 2 } ) then {
            if( !isNil{ _this select 3 } ) then {
              systemChat "all checks passed";
            };
        };
      };
  };
};
</sqf>
<sqf>
// same result as example above, but without negation.
[ controlNull, objNull, 0, true ] call {
  if( isNull( _this select 0 ) ) exitWith {};
  if( isNull( _this select 1 ) ) exitWith {};
  if( isNil{ _this select 2 } ) exitWith {};
  if( isNil{ _this select 3 } ) exitWith {};
  systemChat "all checks passed";
};
</sqf>
In the two examples above, avoiding negation makes the code a lot more simple and avoids many nested checks.
=== The question of optional parameters ===
It can get tricky if a function COULD have a parameter that needs to be handled. For example, in a function where passing a control is optional:
<sqf>
[ controlNull, true ] call {
  // the point is to just continue controlNull is passed, but do something when an actual control is passed.
  if( ctrlIDC( _this select 0 ) > -1 ) then { // ctrlIDC will return -1 if it checks a controlNull
      systemChat "seems to be a control that exists";
  };
  // do some other stuff below here
  if( _this select 1 ) then { systemChat str( random 9000 ) };
};
</sqf>
If someone were to write that same function '''with negation''', one would use <sqf inline>NOT( isNull( _this select 0 ) )</sqf>.<br>
And, using the [[exitWith]] method in the example above will be undesirable because all the code after the check needs to be executed no matter what.<br>
<br>
The conclusion is that when one tries to avoid negation, it is very likely that one needs to use less-than-obvious commands.<br>
That might be ok for someone with enough experience, but it could get confusing for a beginner. Everyone will have to decide that for themselves.<br>
=== the opposite of isNull? ===
There might come a time when you have to check if a parameter is the opposite of [[isNull]], and do something if it is.<br>
With negation, one would simply use <sqf inline>if( not isNull objNull ) then {};</sqf> but when trying to avoid negation, it can get a bit......... creative:<br>
<sqf>
[ player ] call {
  if( ( ( str( _this select 0 ) find "NULL" ) == -1 ) then {};
};
</sqf>
What that does is it wraps the parameter into a string, which for [[objNull]] would become <sqf inline>"<NULL-object>"</sqf>.<br>
Then, simply look for <sqf inline>"NULL"</sqf> in there, and if [[find]] returns -1, it sure is a valid object!
=== Yes, it can get a bit "hacky" ===
Avoiding negation at all cost '''does come with potential "downsides"''' like slower code execution. The previous example is about half as fast as the <sqf inline>!isNull</sqf> approach.<br>
In the end, it all comes down to what you prefer and how much speed you are willing to sacrifice for avoiding negation.<br>
However, there can be instances where avoiding negation is actually faster then negation.<br><br>
An example of how you can approach <sqf inline>!isNull</sqf> differently is like this:
<sqf>
[ objNull, true ] call {
  if( ( _this select 0 ) isEqualType objNull ) then { // will return true even if the object is null.
      if( isNull( _this select 0 ) ) exitWith {}; // yes there is exitWith again :)
      systemChat "that object exists.";
  };
  if( _this select 1 ) then { systemChat "hello world" };
};
</sqf>
The example above is '''slightly''' slower than negation. Again: if fast code execution is the most important thing to you, then by all means: use negation.
{{ Feature | Informative | The content of this page is purely meant to invoke a productive discussion or to inspire someone who might also want to use "positive code".<br>
'''This page means to only offer up another way of writing SQF code, without invoking any hierarchical '''this is better''' nonsense.}}

Latest revision as of 16:41, 27 May 2024