Можно ли инициализировать несколько переменных некоторого типа в одной строке?
Автор вопроса: Edijs KolesnikovičsОтветов: 4
Я пытался писать как можно меньше кода. Итак, я использую:
MyBoolean := Memo1.Text <> '';
вместо
if Memo1.Text = '' then
MyBoolean := true
else
MyBoolean := false;
Объявить и инициализировать
var
myGlobal: integer = 99;
объявить и инициализировать глобальную переменную. Я хотел бы сделать то же самое для локальных переменных, но кажется, что это невозможно, поэтому мне интересно, есть ли способ инициализировать несколько переменных некоторого типа в одной строке, как в C
int x, y, z;
x=y=z=0;
Спасибо.
Ну да и нет. Да для письма, например. X: Integer = 99; Y: Integer = 99; в одной строке, а не в нескольких операторах присваивания. TLama 27.04.2014
Это не так много одной строки, если вы используете Ctrl + D (также известное как форматирование кода). Edijs Kolesnikovičs 27.04.2014
Да, но нет возможности инициализировать несколько переменных в одном выражении. И я рад, что это так, поскольку такое утверждение, как x=y=z=0, мне довольно трудно читать. Лично я бы написал даже это в несколько строк. TLama 27.04.2014
@TLama Почему x=y=z=0 трудно читать или непонятно? Это также стандартная математическая запись, и некоторые языки программирования действительно допускают такой синтаксис. Что, если вместо 0 присваиваемое значение было получено от вызова дорогостоящей (трудоёмкой) функции? Этот синтаксис потребует только одного вызова. Чтобы избежать множественных вызовов в Delphi, вам нужно создать временную переменную, присвоить ей результат функции, а затем иметь несколько строк, присваивающих временное значение переменным. Это было бы если не менее ясно, то уж точно менее изящно. В этом синтаксисе есть. alcalde 27.04.2014
Эджис, я восхищаюсь твоей приверженностью DRY (не повторяйся). К сожалению, Delphi имеет тенденцию принимать форму WET (нам нравится печатать или писать все дважды). Существует много синтаксического сахара, который язык не реализует, что может сократить дублированный код, например. тернарный оператор: x, если a else c, множественное присваивание, лучший приоритет оператора (чтобы избежать необходимости в круглых скобках в операторах с логическими операторами), оператор мощности, шаг в цикле for, строки в операторах case, нотация среза, вывод типа и т. д. Я надеюсь, что когда они перейдут на. alcalde 28.04.2014
@alcalde, почему? Я не знаю. Может быть, потому что, когда я что-то читаю, мой мозг обычно меньше сосредотачивается на том, что находится в середине выражения. Так что, может быть, я боюсь потерять эти переменные y и z при чтении, я не знаю. А насчет временных переменных, что с ними не так? Я скорее буду четко видеть написанное, чем бояться лишнего задания. Кроме того, в сгенерированном ассемблерном коде будет то же самое. Или вы думаете, что есть одна инструкция, которая будет присваивать возвращаемое значение функции сразу трем переменным? TLama 28.04.2014
Вы можете инициализировать только одну локальную переменную для каждого оператора.
Ответ 2 · рейтинг 6 · kludg
В C присваивание представляет собой выражение (возвращает значение).
В Паскале присваивание представляет собой инструкцию (не возвращает значение).
Разница имеет некоторые интересные последствия. Например, в C оба
while (x=0)
а также
while (x==0)
являются синтаксически допустимыми конструкциями (это источник бесчисленных ошибок), в то время как в Паскале
while (x:=0)
является синтаксически недопустимым, поскольку x:=0 является оператором.
Ответ 3 · dummzeuch
Конечно, можно было бы написать функцию
function AssignInteger(var _AssignTo: integer; _Value: integer): integer;
begin
Result := _Value;
_AssignTo := _Value;
end;
и используйте его так:
var
i, j, k: integer;
begin
i := AssignInteger(j, AssignInteger(k, 5));
Но это не совсем то, что вы хотите, говоря, что вы хотите написать как можно более короткий код.
Я указываю это, тем не менее, на всякий случай.
Ответ 4 · Disillusioned
Как говорит dummzeuch, вы можете написать свою собственную процедуру. Однако я бы предпочел вариант с подписью типа: procedure AssignIntegers(AValue, ATargetArray);. И в идеале вызовите процедуру с помощью: AssignInteger(99, [X, Y, Z]);.
К сожалению, идеальный вариант не работает, но следующая процедура достаточно близка и должна быть достаточной. Он работает, беря указатели на целые числа, которые необходимо присвоить.
procedure AssignIntegers(AValue: Integer; const ATargets: array of PInteger);
var
I: Integer;
begin
for I := Low(ATargets) to High(ATargets) do
ATargets[I]^ := AValue;
end;
Следующий тестовый пример DUnit демонстрирует, что он работает. Вы даже можете держать под рукой массив этих целочисленных указателей, чтобы переназначить их в любое время.
type
TArrayPInteger = array of PInteger;
procedure TDelphiTests.TestAssignIntegers;
var
X,Y,Z: Integer;
LGroup: TArrayPInteger;
begin
AssignIntegers(1, [@X, @Y, @Z]); { Pass open arrray using addresses of integers to initialise }
CheckEquals(1, X);
CheckEquals(1, Y);
CheckEquals(1, Z);
LGroup := TArrayPInteger.Create(@X, @Y); { Handy technique to initialise dynamic arrays }
AssignIntegers(2, LGroup);
CheckEquals(2, X);
CheckEquals(2, Y);
CheckEquals(1, Z); { Not part of group }
end;
Предупреждение
Единственным реальным недостатком является то, что вы теряете проверку типов. Компилятор не помешает вам передать адрес нецелочисленных типов. Это может привести к повреждению данных других структур или нарушению прав доступа.