Jump to content
Luft08

Scope of private variables

Recommended Posts

My editor flags a problem with code like this:

private _foo = [];

myFunction = {
	_foo pushBack 1;
};

It claims that _foo inside the function is not declared. This has got to be a scope problem. Even though all code is within the same sqf file the variables inside the function are not considered to be within the same scope. This kind of makes sense. Once declared myFunction can be called from anywhere can't it?

 

Is their any way to get the function to use the outer _foo that is declared? Can an inline function take parameters?

 

Thanks.

 

To be more complete this is (more or less) what thinking about passing parameters:

if(!isServer) exitWith {};

[true, ["seePriestTask"], ["Go talk to the Priest in Chernogorsk", "See Priest", "priestMarker"], priest_1, "ASSIGNED", 1, true, "mil_join", true] call BIS_fnc_taskCreate;

_nearPriestArray = [];

playerNearPriest = {
	params ["_nearPriestArray"];
	
	private _return = false;
	{
		if ((_x distance priest_1) < 3) then {
			_nearPriestArray pushBack _x;
			_return = true;
		};
	} forEach activePlayerArray;
	_return
};



if (playerNearPriest) then {
// Do stuff
};

 

Share this post


Link to post
Share on other sites

It's still a local variable. You can't define a local in one location then reference it in another. That's the nature of a local variable.

  • Like 1

Share this post


Link to post
Share on other sites

Thanks Harzach. I was thinking that because everything resided inside the same sqf file that all variables would be withing the same scope. But obviously a function (even one inside the same sqf file) has it's own scope.

 

So the question becomes how to pass information into the inline function. I want to use the function to get a list of any players who are close enough to a priest to talk to him so that I can set a "talk to the priest" action.

 

Maybe instead of the function returning a boolean it should return an array populated with the player objects that meet the condition?

Share this post


Link to post
Share on other sites

You dont actually need the function to achieve your goal.

Spoiler

if(!isServer) exitWith {};

[true, ["seePriestTask"], ["Go talk to the Priest in Chernogorsk", "See Priest", "priestMarker"], priest_1, "ASSIGNED", 1, true, "mil_join", true] call BIS_fnc_taskCreate;

_nearPriestArray = allPlayers select{ alive _x && { _x distance priest_1 < 3 } };

if (count _nearPriestArray > 0) then { //Or !( _nearPriestArray isEqualTo [] ) 
	// Do stuff
};

 

 

Although this does not answer your question about local variable scope.

You original code would work( return true, not fill you array ) if you actually called the function, rather than placing some code( playerNearPriest ) in an if statement, that will only cause you errors.

Its the same as saying if ( {} ) then makes no sense, no matter what is inside the code braces.

if(!isServer) exitWith {};

[true, ["seePriestTask"], ["Go talk to the Priest in Chernogorsk", "See Priest", "priestMarker"], priest_1, "ASSIGNED", 1, true, "mil_join", true] call BIS_fnc_taskCreate;

_nearPriestArray = [];

playerNearPriest = {
	private _return = false;
	{
		if ((_x distance priest_1) < 3) then {
			_nearPriestArray pushBack _x;
			_return = true;
		};
	} forEach activePlayerArray;
	_return
};



if (call playerNearPriest) then {
	// Do stuff with _nearPriestArray
};

Here the code( playerNearPriest ) is called in the if statement. _nearPriestArray is available within the function as it is defined in a higher scope( the reason we use private or params to signify the variable is not to be confused with/overwrite a variable with the same name in a higher scope ).

For instance...

someFunctionWithPrivateVar = {
	params[ "_myVar" ]; //declare _myVar as private/a new variable, separate to any _myVar in a higher scope
	
	hint format[ "_myVar == 5 is %1", _myVar == 5 ];	//nil undefined, error on comparison, as _myVar was defined in the line above but was not given a value(nil)
};

someFunction = {
	hint format[ "_myVar == 5 is %1", _myVar == 5 ];	//true
	_myVar = 7;	
};

someOtherFunction = {
		
	if ( true ) then {		
		
		if ( true ) then {
			
			_mySecondVar = 3;			
			
			hint format[ "_myVar == 5 is %1", _myVar == 5 ];	//true
			hint format[ "_mySecondVar == 3 is %1", _mySecondVar == 3 ];	//true
			
			call someFunction;
			
		};
		
		hint format[ "_mySecondVar == 3 is %1", _mySecondVar == 3 ];	//nil undefined, error on comparison as mySecondVar was defined in the scope of the if statement that we are now outside of
	};
	
	hint format[ "_myVar == 5 is %1", _myVar == 5 ];	//false its now 7, from call to someFunction
};

_myVar = 5;

call someOtherFunction;
call someFunctionWithPrivateVar;

hint format[ "_myVar == 7 is %1", _myVar == 7 ];	//true

 

21 hours ago, Luft08 said:

I was thinking that because everything resided inside the same sqf file that all variables would be withing the same scope. But obviously a function (even one inside the same sqf file) has it's own scope.

Even though it has its own scope it still has access to any local variables from a higher scope, even if the function was in a different file.

 

21 hours ago, Luft08 said:

So the question becomes how to pass information into the inline function. I want to use the function to get a list of any players who are close enough to a priest to talk to him so that I can set a "talk to the priest" action.

As mentioned above, if you didnt private the variable( params ) within your function, it would have changed your originally defined variable from the higher scope.

The other is to not define the variable outside the function but instead return a list of near players and then check that the array actually holds any results.

if(!isServer) exitWith {};

[true, ["seePriestTask"], ["Go talk to the Priest in Chernogorsk", "See Priest", "priestMarker"], priest_1, "ASSIGNED", 1, true, "mil_join", true] call BIS_fnc_taskCreate;

playerNearPriest = {
	private _nearPriestArray = [];	//Private,this variable exist in this scope and any child scopes
	{
		//this is a child scope
		if ((_x distance priest_1) < 3) then {
			//this is another child scope
			_nearPriestArray pushBack _x;
		};
	} forEach activePlayerArray;
	_nearPriestArray;	//Return the array
};


_nearPriestArray = call playerNearPriest;	//_nearPriestArray is a newly defined variable in the current scope that holds the returned value from the function call
if !( _nearPriestArray isEqualTo [] ) then {
	// Do stuff with _nearPriestArray
};

Hope that makes sense.

  • Like 4
  • Thanks 1

Share this post


Link to post
Share on other sites

Thanks Larrow, You have been incredibly helpful!

Share this post


Link to post
Share on other sites
On 7/30/2020 at 3:22 PM, Larrow said:

Even though it has its own scope it still has access to any local variables from a higher scope, even if the function was in a different file.

I do have one question. How do you "match up" scopes that are in a different file?  Is it something like counting the depth of the nesting?

File 1:

{ // scope 1

     _var_1 (Would having the "private" declaration not allow access in File 2, scope 2?)

     { // scope 2

         code

     }

}

 

File 2:

{ // scope 1 (as in File 1)

    { // scope 2 (as in file 1)

      _var_1 from file 1 is visible here.

    }

}

       

Share this post


Link to post
Share on other sites
On 7/30/2020 at 4:17 PM, Luft08 said:

My editor flags a problem with code like this:

The problem is with your editor

  • Like 1

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

×