Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Сообщения за день
 

Вернуться   Форум Flasher.ru > Блоги > КривыеВелосипеды

Оценить эту запись

functionCallToString и arrayToString

Запись от trashcoder размещена 24.01.2013 в 03:02
Обновил(-а) trashcoder 24.01.2013 в 16:32

Данный блог не претендует на полезность, правильность кода, прямоту рук, отсутствие багов и интересность. Здесь вряд ли кто-нибудь узнает что-то новое. Как следует из названия, всё здесь публикуемое почти наверняка написано кем-то намного раньше и намного лучше. Я же просто буду выкладывать обрывки кода, которые жалко держать при себе в ящике стола. Пользуйтесь, критикуйте, не обращайте внимания — всё в равной степени хорошо.

Иногда к функции приходится подбирать кучу параметров методом проб и ошибок. Хочется повертеть их так и сяк, а потом просто захардкодить все аргументы. Можно сделать GUI, который позволит на ходу подобрать параметры, а потом вручную их переписывать, а можно сделать trace всех параметров через запятую и в скобочках, чтобы просто их скопировать. Всего лишь это и делает описываемая функция, за тем исключением, что выводит вызов функции так, как её написали бы вы в коде, т.е. не все аргументы, а только те, что отличаются от значения по умолчанию.
Взять хотя бы ColorTransform:
Код AS3:
ColorTransform(redMultiplier:Number=1.0, greenMultiplier:Number=1.0, blueMultiplier:Number=1.0, alphaMultiplier:Number=1.0, redOffset:Number=0, greenOffset:Number=0, blueOffset:Number=0, alphaOffset:Number=0)
// Дальше как обычно
new ColorTransform(1.0, 1.0, 5.0, 2.4, 128)
// Изменили только alphaOffset, но придется писать все аргумены до него.
new ColorTransform(1.0, 1.0, 1.0, 1.0, 0, 0, 0, 255)
Ну вы поняли. Покажу сразу код:
Код AS3:
/**
 * Формирует строку, выглядящую как вызов функции с минимально возможным количеством передаваемых параметров.
 * @param name Название функции.
 * @param mandatoryArgs Array Массив со значениями обязательных параметров, передаваемых в функцию.
 * @param optionalArgs Array Массив со значениями необязательных параметров, передаваемых в функцию.
 * @param defaultVals Array Массив со значениями по умолчанию необязательных параметров функции.
 * @param stringsInQuotes Boolean Выводить ли аргументы-строки в кавычках. По умолчанию true.
 * @return String
 */
public static function functionCallToString(name:String, mandatoryArgs:Array = null, optionalArgs:Array = null, defaultVals:Array = null, stringsInQuotes:Boolean = true):String
{
	var s:String = name + "(";
 
	var numArgs:int = optionalArgs.length;
	if(defaultVals && defaultVals.length && numArgs <= defaultVals.length)
	{
		while(numArgs >= 0)
		{
			numArgs--;
			if(optionalArgs[numArgs] != defaultVals[numArgs])
				break;
		}
	}
 
	var ml:Boolean = mandatoryArgs && mandatoryArgs.length;
	var i:int, n:int, val:Object;
 
	if(ml)
	{
		for(i = 0, n = mandatoryArgs.length; i < n; i++)
		{
			if(i > 0) s += ", ";
			val = mandatoryArgs[i];
			if(val is Array) s += arrayToString(val as Array, stringsInQuotes);
			else s += (val is String) && stringsInQuotes ? '"' + val + '"' : val == null ? "null" : val.toString();
		}
	}
 
	if(optionalArgs && optionalArgs.length)
	{
		for(i = 0; i <= numArgs; i++)
		{
			if(ml || i > 0) s += ", ";
			val = optionalArgs[i];
			if(val is Array) s += arrayToString(val as Array, stringsInQuotes);
			else s += (val is String) && stringsInQuotes ? '"' + val + '"' : val == null ? "null" : val.toString();
		}
	}
 
	s += ");"
	return s;
}
 
/**
 * Переводит массив в строку в том виде, в котором его можно вставить в код. Строки внутри массива будут представлены в кавычках.
 * @param array Array
 * @param stringsInQuotes Boolean Выводить ли элементы-строки в кавычках. По умолчанию true.
 * @param recursive Boolean Если ture, преобразует все вложенные массивы. Если массив содержит сам себя или является одним из своих родителей,
 * вместо массива выведет "`recursion (уровень_вложенности)`". По умолчанию true.
 * Если false, вместо массива выведет "[`Array`]".
 * @return String
 */
public static function arrayToString(array:Array, stringsInQuotes:Boolean = true, recursive:Boolean = true):String
{
	if(array == null) return "null";
 
	if(recursive) return recursiveArrayToString(array, stringsInQuotes);
 
	var s:String = "[";
	for (var i:int = 0, n:int = array.length; i < n; i++) 
	{
		if(i > 0) s += ", ";
		var val:Object = array[i];
		if(val is Array)
			s += "[`Array`]"
		else
			s += (val is String) && stringsInQuotes ? '"' + val + '"' : val == null ? "null" : val.toString();
	}
 
	s += "]";
	return s;
}
 
private static function recursiveArrayToString(array:Array, stringsInQuotes:Boolean = true, chain:Array = null):String
{
	var s:String, i:int;
	if(chain)
	{
		var index:int = chain.indexOf(array);
		if(index != -1) 
		{
			s = "`recursion (";
			var count:int = chain.length - index - 1;
			if(count == 0)
			{
				s += "self";
			}
			else
			{
				s += "parent";
				for(i = 1; i < count; i++) 
				{
					s += " parent";
				}
			}
			s += ")`";
			return s;
		}
		chain.push(array);
	}
	else
	{
		chain = [array];
	}
 
	s = "[";
	var n:int = array.length;
	for(i = 0; i < n; i++) 
	{
		if(i > 0) s += ", ";
		var val:Object = array[i];
		if(val is Array)
		{
			s += recursiveArrayToString(val as Array, stringsInQuotes, chain.slice());
		}
		else
		{
			s += (val is String) && stringsInQuotes ? '"' + val + '"' : val == null ? "null" : val.toString();
		}
	}
	s += "]";
 
	return s;
}
functionCallToString принимает сначала массив с обязательными параметрами mandatoryArgs, которые добавятся в выходную строку в любом случае, потом массив с необязательными optionalArgs и их знаниями defaultVals, которые функция сравнит между собой, и если на конце массивов элементы совпадают, не включит их в выдачу. Если нужно передать функцию сложное выражение или какой-нибудь новый объект, полезно будет отключить stringsInQuotes.
Код AS3:
// Например, для
addBoss(new LevelBoss("TheGreatMightyPoo", true), 128, "blablabla");
// нужно
var bossString:String = functionCallToString("new LevelBoss", [Bosses.POO], [_isSinging], [...], true); // сначала с кавычками
var funcString:String = functionCallToString("addBoss", [bossString, ...], [...], [...], false); // потом без.
// Чтобы не получилось
addBoss("new LevelBoss('TheGreatMightyPoo', true)", 128, "blablabla");
Да, есть еще функция arrayToString, что она делает понятно из названия, только она делает это еще и рекурсивно и ей не страшен stack overflow. functionCallToString автоматически "развернёт" массив, если такой найдется среди аргументов. Объекты в {} она не выводит, но для этого есть JSON.
Что-то много слов для столь очевидного материала, но всё же подведу итог.
Полезность сего алгоритма сомнительна, но с помощью него можно легко подобрать параметры в игре с физическим движком, или использовать для автоматической генерации кода в качестве примера к какой-нибудь библиотеке, например, как в TweenLite.

Пример использования:
Код AS3:
functionCallToString("perlinNoise", [baseXSlider.value, baseYSlider.value, numOctavesNumericStepper.value, randomSeedWiget.value, stitchCheckBox.selected, fractalNoiseCheckBox.selected], [channelOptionsWiget.channelOptions, grayScaleCheckBox.selected , offsets], [7, false , null], false);
FunctionTraceExample.swf   (57.6 Кб)
Вложения
Тип файла: swf FunctionTraceExample.swf (57.6 Кб, 379 просмотров)
Всего комментариев 0

Комментарии

 
Последние записи от trashcoder

 


Часовой пояс GMT +4, время: 19:27.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.