Перейти к содержимому


Фотография

Объясните getVariable и set


Лучший Ответ Sa-Matra , 04 May 2015 - 15:10

Дело в том, что операция присваивания (=) не копирует массив, как это делает с любыми другими типами данных, а лишь присваивает переменной ссылку на массив, чтобы не создавать в памяти одни и те же данные по многу раз, ведь массив может быть очень большой структурой имеющий члены с глубокой вложенностью, с другими ссылками на массив, все это копировать очень затратно и не почти никогда не нужно программисту. А вот сложение и вычитание массивов создает новые массивы. Объясняю, что происходит в коде автора темы:

// Получаем ссылку на массив из профиля и кладем ее в локальную переменную
_myVar1 = profileNamespace getVariable "MyVar1";

// Вызываем команду складывания массивов, которая создает **новый** массив из того, что по ссылке в _myVar1 и нового массива [4]
_myVar1 = _myVar1 + [4];

// Вызываем команду вычитания массивов, которая создает **новый** массив из того, что по ссылке в _myVar1 и нового массива [4]
_myVar1 = _myVar1 - [4];

// Вызываем команду установки элемента в массиве
_myVar1 set [1,0];
Таким образом код два раза создает новый массив и потом делает set [1,0] в уже другом массиве, а не том, что лежит в profileNamespace.
Вывод: Команды <array> + <array> и <array> - <array> создают новый, а не изменяют старый!

Вопрос: Как изменять массив, не копируя его при каждой операции или один раз получив массив откуда-то, оперировать только им, а не его копиями.
Ответ: В Arma 3 появились удобные команды позволяющие проводить похожие операции, изменяющие оригинальный массив, а не создающие копию. Эти команды:

https://community.bi...m/wiki/pushBack
https://community.bi...m/wiki/deleteAt
https://community.bi...com/wiki/append

Код автора с новыми командами и ожидаемым результатом:
profileNamespace setVariable ["MyVar1",[1,2,3]];

_myVar1 = profileNamespace getVariable "MyVar1";
_myVar1 pushBack 4;
_myVar1 deleteAt (_myVar1 find 4);
_myVar1 set [1,0];

hint str (profileNamespace getVariable "MyVar1"); // [1,0,3]

---

p.s. profileNamespace добавили не только в А3, а есть он еще и в А2ОА, правда с багом на выделенном сервере, где сохраненные данные не грузятся, т.е. работает только для игроков. Перейти к сообщению


  • Авторизуйтесь для ответа в теме
Сообщений в теме: 12

#1 OFFLINE   vlad333000

vlad333000

    Полковник

  • Пользователи
  • 3224 сообщений
  • Откуда:Кострома

Отправлено 03 May 2015 - 20:37

Объясните дураку:
1-ый случай
//Script1.sqf
profileNamespace setVariable ["MyVar1",[1,2,3]];

//Script2.sqf
_myVar1 = profileNamespace getVariable "MyVar1";
_myVar1 set [1,0];
//Result: _myVar1  = [1,0,3] profileNamespace -> MyVar1 = [1,0,3]
2-ой случай
//Script1.sqf
profileNamespace setVariable ["MyVar1",[1,2,3]];

//Script2.sqf
_myVar1 = profileNamespace getVariable "MyVar1";
_myVar1 = _myVar1 + [4];
_myVar1 = _myVar1 - [4];
_myVar1 set [1,0];
//Result: _myVar1  = [1,0,3] profileNamespace -> MyVar1 = [1,2,3]
Получается каждый раз придется так мучатся (Как во 2-ом случае) что бы изменить что-то в массиве без изменения "оригинального"? Или тогда, что возвращает getVariable (BIS: Return the value of variabl)?

Сообщение отредактировал vlad333000: 03 May 2015 - 20:55

  • 0

#2 OFFLINE   SteelRat

SteelRat

    Полковник

  • Пользователи
  • 3241 сообщений
  • Откуда:РФ

Отправлено 04 May 2015 - 00:36

Интересно, но как то не логично.

По идее тут

_myVar1 = profileNamespace getVariable "MyVar1";

Объявляется локальная переменная _myVar и ей присваивается значение переменной из профиля, а не ссылка на саму переменную.

Фигня какая то действительно.


  • 1

#3 OFFLINE   SteelRat

SteelRat

    Полковник

  • Пользователи
  • 3241 сообщений
  • Откуда:РФ

Отправлено 04 May 2015 - 01:50

Надо же какая интересная фигня получается), не зря говорят, век живи, век учись!

 

И это вот тоже имеет тоже эффект, что и с профильной переменной

0 = [] spawn {
	missionNamespace setVariable ["varTest", [1,2,3]];
	systemChat format["in profile: %1", missionNamespace getVariable "varTest"];
	_varTest = missionNamespace getVariable "varTest";
	systemChat format["_varTest: %1", _varTest];
	_varTest set [1, 0];
	systemChat format["_varTest: %1", _varTest];
	systemChat format["in profile: %1", missionNamespace getVariable "varTest"];
}

Я так понимаю это такая фишка команды set применительно к массивам, до тех пор пока вы не изменили размер массива, вы можете с помощью команды set воспользоваться локальной переменной как ссылкой на переменную в профиле, как пример.

 

А вот это уже работает как вам бы хотелось

0 = [] spawn {
	profileNamespace setVariable ["varTest", [1,2,3]];
	systemChat format["in profile: %1", profileNamespace getVariable "varTest"];
	_varTest = [];
	{
		_varTest pushBack _x;
	} foreach (profileNamespace getVariable "varTest");
	systemChat format["_varTest: %1", _varTest];
	_varTest set [1, 0];
	systemChat format["_varTest: %1", _varTest];
	systemChat format["in profile: %1", profileNamespace getVariable "varTest"];
}

Итог, если вам придётся очень часто обращаться к переменной в профиле не изменяя случаем её значения, то как вариант функция

ptm_fnc_getProfileData = {
	_ret = [];
	{
		_ret pushBack _x;
	} foreach (profileNamespace getVariable _this);
	_ret
}
_varTest = "varTest" call ptm_fnc_getProfileData;

  • 1

#4 OFFLINE   Dimon UA

Dimon UA

    Ст.сержант

  • Пользователи
  • 304 сообщений
  • Откуда:Севастополь

Отправлено 04 May 2015 - 02:09

ммм... я наверное многое упустил: а с каких пор добавили команду profileNamespace?


  • 0

#5 OFFLINE   SteelRat

SteelRat

    Полковник

  • Пользователи
  • 3241 сообщений
  • Откуда:РФ

Отправлено 04 May 2015 - 02:25

ммм... я наверное многое упустил: а с каких пор добавили команду profileNamespace?

Пожалуйста Войдите или Зарегистрируйтесь чтобы увидеть скрытое содержание

Ключевая фраза

 

The variables are stored next to the user profile in a file named myUsername.vars.TakeOnHProfile (e.g. in the My Documents\Take On Helicopters folder).


ЗЫ

Я в смысле о том, что в трёшке, если мне память не изменяет, эта команда была с самого начала.


  • 0

#6 OFFLINE   Dimon UA

Dimon UA

    Ст.сержант

  • Пользователи
  • 304 сообщений
  • Откуда:Севастополь

Отправлено 04 May 2015 - 02:33

круто... не знал.


  • 0

#7 OFFLINE   vlad333000

vlad333000

    Полковник

  • Пользователи
  • 3224 сообщений
  • Откуда:Кострома

Отправлено 04 May 2015 - 14:03

Update: Полностью универсальный вариант (Получаем переменную из любого места):
myTag_fnc_getVar = {
	private ["_return","_var","_space","_default"];

	_var = _this select 0;
	_space = _this select 1;
	_default = "['nil']";
	_return = [];

	if ((count _this) > 2) then {
		_default = _this select 2;
	};

	{_return pushBack _x} forEach (call compile format ["%1 getVariable ['%2',%3]",_space,_var,_default]);

	_return;
};
Вызов:
myVar1 = ["VarName","VariableSpace"] call myTag_fnc_getVar;
myVar2 = ["VarName","VariableSpace","DefaultValue"] call myTag_fnc_getVar;
/*
VarName - String - переменная ("myVar1","myVar2"...)
VariableSpace - String - место, где находится переменная (Может быть чем-угодно: "missionNamespace","player","men1","cursorTarget"... включая скрипт)
DefaultValue - String с массивом - стандартное значение (Если нужно) ("[1,2,3]","['string']","['bob']","[1]","[myGlobalVar]"... или скрипт, возвращающий массив)

PS Сама переменная должна-быть массивом :)
*/

Сообщение отредактировал vlad333000: 04 May 2015 - 15:15

  • 0

#8 OFFLINE   Sa-Matra

Sa-Matra

    Ефрейтор

  • Пользователи
  • 97 сообщений

Отправлено 04 May 2015 - 15:10   Лучший Ответ

Дело в том, что операция присваивания (=) не копирует массив, как это делает с любыми другими типами данных, а лишь присваивает переменной ссылку на массив, чтобы не создавать в памяти одни и те же данные по многу раз, ведь массив может быть очень большой структурой имеющий члены с глубокой вложенностью, с другими ссылками на массив, все это копировать очень затратно и не почти никогда не нужно программисту. А вот сложение и вычитание массивов создает новые массивы. Объясняю, что происходит в коде автора темы:

// Получаем ссылку на массив из профиля и кладем ее в локальную переменную
_myVar1 = profileNamespace getVariable "MyVar1";

// Вызываем команду складывания массивов, которая создает **новый** массив из того, что по ссылке в _myVar1 и нового массива [4]
_myVar1 = _myVar1 + [4];

// Вызываем команду вычитания массивов, которая создает **новый** массив из того, что по ссылке в _myVar1 и нового массива [4]
_myVar1 = _myVar1 - [4];

// Вызываем команду установки элемента в массиве
_myVar1 set [1,0];
Таким образом код два раза создает новый массив и потом делает set [1,0] в уже другом массиве, а не том, что лежит в profileNamespace.
Вывод: Команды <array> + <array> и <array> - <array> создают новый, а не изменяют старый!

Вопрос: Как изменять массив, не копируя его при каждой операции или один раз получив массив откуда-то, оперировать только им, а не его копиями.
Ответ: В Arma 3 появились удобные команды позволяющие проводить похожие операции, изменяющие оригинальный массив, а не создающие копию. Эти команды:

Пожалуйста Войдите или Зарегистрируйтесь чтобы увидеть скрытое содержание


Пожалуйста Войдите или Зарегистрируйтесь чтобы увидеть скрытое содержание


Пожалуйста Войдите или Зарегистрируйтесь чтобы увидеть скрытое содержание



Код автора с новыми командами и ожидаемым результатом:
profileNamespace setVariable ["MyVar1",[1,2,3]];

_myVar1 = profileNamespace getVariable "MyVar1";
_myVar1 pushBack 4;
_myVar1 deleteAt (_myVar1 find 4);
_myVar1 set [1,0];

hint str (profileNamespace getVariable "MyVar1"); // [1,0,3]

---

p.s. profileNamespace добавили не только в А3, а есть он еще и в А2ОА, правда с багом на выделенном сервере, где сохраненные данные не грузятся, т.е. работает только для игроков.

Сообщение отредактировал Sa-Matra: 04 May 2015 - 15:41

  • 2

#9 OFFLINE   SteelRat

SteelRat

    Полковник

  • Пользователи
  • 3241 сообщений
  • Откуда:РФ

Отправлено 04 May 2015 - 18:20

По сути я именно это я и изложил, только другими словами.

 

А здесь я не совсем уловил вашу мысль

 

т.е. работает только для игроков.          

Как по мне так с этим всё нормально, на то это и

profileNamespace

который лежит на клиенте и для клиента.

 

ЗЫ

Или на сервере и для сервера.


 

Как изменять массив, не копируя его при каждой операции или один раз получив массив откуда-то, оперировать только им, а не его копиями.
 

Перед топикмейкером как раз и стояла задача не изменять оригинальные данные.


Сообщение отредактировал SteelRat: 04 May 2015 - 18:18

  • 0

#10 OFFLINE   SteelRat

SteelRat

    Полковник

  • Пользователи
  • 3241 сообщений
  • Откуда:РФ

Отправлено 04 May 2015 - 18:28

myTag_fnc_getVar = {
	private ["_return","_var","_space","_default", "_data"];

	_var = _this select 0;
	_space = _this select 1;
	_default = "['nil']";
	_return = [];

	if ((count _this) > 2) then {
		_default = _this select 2;
	};

	_data = call compile format ["%1 getVariable ['%2',%3]",_space,_var,_default];
	
	if (typename _data == typename []) then {
		// если данные представляет массив то
		{_return pushBack _x} forEach _data;
	} else {
		// это не массив
		_return = _data;
	};

	_return;
};

  • 1

#11 OFFLINE   Sa-Matra

Sa-Matra

    Ефрейтор

  • Пользователи
  • 97 сообщений

Отправлено 04 May 2015 - 21:05

Я не понимаю зачем вы делаете какие-то функции? Если нужна полная копия массива, то для этого есть команда "+ <array>", которая делает копию.

_array1 = [1,2,3];
_array2 = _array1;
_array3 = +_array1;

_array1 set [1, 0];

systemChat str _array2; // [1,0,3]
systemChat str _array3; // [1,2,3]

---

Что касается profileNamespace, то в A2OA сейчас баг, который не загружает переменные из профиля на выделенном сервере.

Попробуйте выполнить код на выделенном сервере
diag_log format ["profileNamespace getVariable ""test"" = %1", profileNamespace getVariable "test"];
profileNamespace setVariable ["test", random 100000];
diag_log format ["profileNamespace getVariable ""test"" = %1", profileNamespace getVariable "test"];
saveProfileNamespace;
Потом перезагрузить сервер и выполнить снова, "test" будет неопределена, несмотря на то что в прошлый запуск туда что-то сохранили.

Сообщение отредактировал Sa-Matra: 04 May 2015 - 21:32

  • 0

#12 OFFLINE   SteelRat

SteelRat

    Полковник

  • Пользователи
  • 3241 сообщений
  • Откуда:РФ

Отправлено 04 May 2015 - 21:50

 

Я не понимаю зачем вы делаете какие-то функции? Если нужна полная копия массива, то для этого есть команда "+ <array>", которая делает копию.
 

 

Сударь! Не ужели мне нужно объяснять, вам, зачем делают функции?

 

 

Итог, если вам придётся очень часто обращаться к переменной в профиле не изменяя случаем её значения, то как вариант функция

 

Одна строка вызова, весьма смахивающая на вызов самой команды.

Я не утверждаю что нужно делать именно так, на вкус и цвет товарищей нет.

 

Так и было заявлено

то как вариант функция

 


 

Что касается profileNamespace, то в A2OA сейчас баг, который не загружает переменные из профиля на выделенном сервере.
 

 

Теперь я вас понял.


  • 0

#13 OFFLINE   SteelRat

SteelRat

    Полковник

  • Пользователи
  • 3241 сообщений
  • Откуда:РФ

Отправлено 04 May 2015 - 21:58

ЗЫ

Кстати, я бы, от себя лично и от имени многих начинающих, попросил бы вас изложить то, что вы озвучили здесь про массивы, в уроках по скрипто писанию. Информация полезная, а главное важная. Не помню, упоминается ли в уроках про массивы такой нюанс.

 

http://arma3.ru/foru...kriptopisaniiu/


  • 0




Яндекс.Метрика