Есть ли встроенная функция для очистки всех значений переменных
Я ищу способ очистить все мои массивы в программе Perl.
В настоящее время я вызываю подпрограмму, которая явно "сбрасывает" все массивы:
sub clear_arrays{(@array1,@array2,@array3)=((),(),());}
Это заставляет меня найти все массивы в программе и буквально ссылаться на них в подпрограмме.
Я посмотрел на Perldoc для reset
, undef
, а также delete
но не мог интерпретировать ни один из них таким образом, чтобы очистить все массивы.
Есть ли встроенная функция Perl, которая может сделать это?
Если нет, есть ли функция, которая будет возвращать массив всех переменных массива?
Пример:
my @prog_arrays = getarrays();
foreach(@prog_arrays){$_ = ();}
куда getarrays()
может быть встроенной функцией Perl, которая возвращает любые / все инициализированные массивы в программе.
РЕДАКТИРОВАТЬ:
В моей конкретной ситуации используются только два глобальных массива, которые необходимо сбросить. Я расширил вопрос из любопытства, а не необходимости. По сути, мои глобалы
@email_subject
& @email_msg
,Они имеют значения, вставленные в них по мере выполнения сценария и сбора / анализа данных. В конце сценария отправляется сообщение электронной почты, и сценарий может выполняться снова в зависимости от переменной условия цикла.
Если он запустится снова, мне нужно очистить эти 2 глобальные переменные, чтобы они могли быть снова объединены во время следующего цикла цикла. Это не убивает меня, чтобы очистить эти два массива с помощью буквальной ссылки, но мне было просто интересно, есть ли в Perl какая-то встроенная функция для очистки массивов без буквальной ссылки на них.
Возможно, это не лучший способ сделать это, но это был первый интуитивный вариант, который я рассмотрел.
3 ответа
Как упоминалось в других ответах, ваш запрос говорит о более серьезной проблеме с дизайном вашей программы. Вы должны либо использовать лексические выражения, которые выпадают из области видимости, либо тщательно управлять всеми вашими глобальными массивами и создать функцию, которая очистит их для вас.
Если вы настаиваете на том, чтобы забивать каждый массив в вашем пространстве имен, по крайней мере позаботьтесь и убедитесь, что вы не записываете значения, которые могут понадобиться Perl:
for (keys %::) { # for everything in `package main;`
if (*{$::{$_}}{ARRAY}) { # if there is an array in the slot
# clear it unless it is a "special" array
@{$::{$_}} = () unless /^(?:INC|ISA|EXPORT|EXPORT_OK|ARGV|_|\W)$/
}
}
Я бы написал это так:
my @global_arrays = \our (@foo, @bar, @baz);
sub clear_global_arrays {
@$_ = () for @global_arrays
}
Эффект одинаков для рассматриваемых массивов, но при этом он не рискует заглушить то, что вы не собирались делать. Вы могли бы даже использовать my
скорее, чем our
со вторым примером, в то время как первый пример требует, чтобы переменные были в таблице символов (или определены как our
).
Не используйте глобальные массивы. Это так просто. Лексические массивы ограничены областью, в которой они объявлены, и автоматически запускаются пустыми при входе в область.
Если вы должны использовать глобальные переменные, отслеживание их всех в одном месте является хорошей идеей, так что очистка их не должна быть трудной.
Кто-то когда-то опубликовал позорный инструмент для perlmonks, чтобы делать то, что вы хотите. Код был отозван после большой критики всей идеи; Вы можете прочитать некоторые критики здесь: http://www.perlmonks.org/index.pl?node_id=349496
Тот факт, что вы хотите это кричит "плохой дизайн" для меня. Однако при условии, что вы точно знаете, что делаете с этой радиоактивной цепной пилой, вы можете сделать это, получив доступ к хэшу таблицы глобальных символов. %::
или же %main::
, (Двоеточия являются частью имени.) Этот хеш содержит отображение каждого определенного глобального символа на ссылку на его переменную.
Что-то вроде этого должно быть достаточно:
for my $ref (values %::) {
@{$ref} = ();
}
Отредактировано для удаления проверки ссылок на массив. Все значения на самом деле являются ссылками на typeglob, так что нет необходимости проверять.