Анимация
JavaScript
|
Главная Библионтека 12.5. Определение пакета вызывающей стороны 419 ры, имеющие специальное значение для Perl. Имена функций и локальных переменных записываются в нижнем регистре. Устойчивые переменные модуля (файловые лексические или пакетные глобальные) начинаются с символа верхнего регистра. Если идентификатор состоит из нескольких слов, то для удобства чтения эти слова разделяются символами подчеркивания. Пожалуйста, не разделяйте слова символами верхнего регистра без подчеркиваний - в конце концов, вряд ли вам захотелось бы читать эту книгу без пробелов. !> Смотри также- perlstyle(l); рецепты 10.2-10.3. Лексические переменные с файловой областью действия рассматриваются ъ perlmod(\). 12.5. Определение пакета вызывающей стороны Проблема Требуется узнать текущий или вызывающий пакет. Решение Текущий пакет определяется так: $this pack = PACKAGE ; Пакет вызывающей стороны определяется так: $that pack = callerO; Комментарий Метапеременная PACKAGE возвращает пакет, в котором был откомпилирован текущий код. Значение не интерполируется в строках, заключенных в кавычки: print "I am in package PACKAGE \n"; # НЕВЕРНО! I am in package PACKAGE Необходимость узнать пакет вызывающей стороны чаще возникает в старом коде, которому в качестве входных данных была передана строка для eval, файловый манипулятор, формат или имя манипулятора каталога. Рассмотрим гипотетическую функцию runit: package Alpha; runit(Sline = <TEMP>); package Beta; sub runit { my Scodestr = shift; eval Scodestr; die if S@; Такой подход работает лишь в том случае, если переменная $Ипе является глобальной. Для лексических переменных он не годится. Обходное решение - сделать так, чтобы функция run it принимала ссылку на функцию: package Beta; sub runit { my Scodestr = shift; my Shispack = caller; eval "package $hispack; $codestr"; die If $@; Новое решение не только работает с лексическими переменными, но и обладает дополнительным преимушеством - синтаксис кода проверяется во время компиляции, а это сушествениый плюс. При передаче файлового манипулятора стоит воспользоваться более переносимым решением - функцией Symbol;; qualify. Она получает имя и пакет, для которого оно уточняется. Если имя нуждается в уточнении, оно исправляется, а в противном случае остается без изменений. Однако это решение заметно уступает по эффективности прототипу *. Следующий пример читает и возвращает п строк из файлового манипулятора. Перед тем как работать с манипулятором, функция qualify уточняет его. open (FH, "< /etc/termcap") or die "cant open /etc/termcap- $!"; ($a, $b, $c) = nreadline(3, FH); use Symbol (); use Carp; sub nreadline { my (Scount, Shandle) = @ ; my(@retlist,Sline); croak "count must be > 0" unless Scount > 0; Shandle = Symbol;;qualify($handle, (caller())[0]); croak "need open filehandle" unless defined fileno($handle), push(@retlist, Sline) while defined($line = <$handle>) && Scount--; return @retlist; Если при вызове функции nreadline файловый манипулятор всегда передается в виде тип-глоба .FH, ссылки на глоб \*FH или с помощью объектов FileHandle или 10;; Handle, уточнение не потребуется. Оно необходимо лишь на случай передачи минимального "FH". !> Смотри также- Документация по стандартному модулю Symbol; рецепт 12.12. Специальные метапеременные FILE , LINE и PACKAGE описаны в perldata( 1). 12.6. Автоматизированное выполнение завершающего кода 421 12.6. Автоматизированное выполнение завершающего кода Проблема Требуется создать для модуля начальный и завершающий код, вызываемый автоматически без вмешательства пользователя. Решение Начальный код реализуется просто - разместите нужные команды вне определений подпрограмм в файле модуля. Завершающий код помещается в блок END модуля. Комментарий в некоторых языках программист должен вызвать инициализирующий код модуля, прежде чем вызывать какие-либо его функции. Аналогично, при завершении программы от программиста может потребоваться вызов завершающего кода, выполняющего деинициализацию модуля. В Perl дело обстоит иначе. Инициализирующий код модуля образуют команды, не входящие ни в одну подпрограмму модуля. Этот код выполняется непосредственно при загрузке модуля. Пользователю никогда не приходится следить за вызовом начального кода, поскольку это происходит автоматически. Для чего нужен автоматический вызов завершающего кода? Все зависит от модуля. Допустим, вам захотелось записать информацию о завершении в системный журнал, приказать серверу базы данных актуализировать все незаконченные операции, обновить состояние экрана или вернуть терминал в исходное состояние. Предположим, модуль должен регистрировать начало и завершение своей работы в журнале. Вставьте следующий фрагмент в блок END, чтобы он выполнялся при завершении программы: SLogfile = "/tmp/mylog" unless defined $Logfile; open(LF, »$Logfile") or die "cant append to SLogfile: $!"; select(((select(LF), $=1))[0]); # Отменить буферизацию LF log[iisg("startup"); sub logmsg { my $now = scalar gmtime; print LF "$0 $$ $now: @ \n" or die "write to $Logfile failed: $!"; END { logmsgC"shutdown"); close(LF) or die "close SLogfile failed: $!"; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 [ 134 ] 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |