Анимация
JavaScript


Главная  Библионтека 

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

12.12. Вывод сообщений об ошибках и предупреждений 431

нательным аргументом (и не воспользовались модулем Math::Complex) - возникает исключение с выводом сообщения вида "Can t take sqrt of -3 at /tmp/ negroot line 17", где/tmp/negroot - имя вашей программы. Но если вы напишете собственную функцию с использованием die:

sub even only { my $n = shift;

die "$n is not even" if $n & 1; # Один из способов проверки #....

то в сообщении вместо пользовательского файла, из которого вызывалась ваша функция, будет указан файл, в котором была откомпилирована функция even only. На помощь приходит модуль Сагр. Вместо die мы используем функцию croak:

use Carp; sub even only { my $n = shift;

croak "$n is not even" if $n % 2; Другой способ #....

Если вы хотите просто вывести сообщение с номером строки пользовательской программы, где произошла ошибка, вызовите сагр вместо warn (в отличие от warn и die, завершающий перевод строки в сообщениях сагр и croak не имеет особой интерпретации). Например:

use Carp; sub even only { my $n = shift;

if ($n & 1) { # Проверка нечетности

carp "$n is not even, continuing"; ++$n;

#....

Многие встроенные функции выводят предупреждения лишь при использовании ключа командной строки -w. Переменная $"W сообщает о его состоянии. Например, предупреждения можно выдавать лишь при наличии запроса от пользо-> вателя:

сагр "$п is not even, continuing" if $"W;

Наконец, в модуле Carp существует третья функция - confess. Она работает аналогично сгоак за исключением того, что при аварийном завершении выводится полная информация о состоянии стека, вызовах функций и значениях аргументов.

О Смотри также-

Описание функций warn и die в perlmod{\.y, описание метаиеременных WARN и DIE в разделе «Global Special Arrays» jDer/t)(3r(l) и в рецепте 16.15; документация по стандартному модулю Сагр; рецепт 19.2.



12.13. Косвенные ссылки на пакеты

Проблема

Требуется сослаться на переменную или функцию в пакете, имена которых неизвестны до момента выполнения программы, однако синтаксис Spackname; ;$varname недопустим.

Решение

Воспользуйтесь символическими ссылками: {

по strict refs;

$val = ${ Spackname . "::" . Svarname }; @vals = @{ Spackname . "::" . Saryname ); &{ Spackname . "::" . Sfuncname }("args"); (Spackname . "::" . Sfuncname) -> ("args");

Комментарий

объявление пакета имеет смысл во время компиляции. Если имя пакета или переменной неизвестно до времени выполнения, придется прибегнуть к символическим ссылкам и организовать прямые обращения к таблице символов пакета. Включите в блок директиву по strict refs и постройте строку с полным именем интересующей вас переменной или функции. Затем разыменуйте полученную строку так, словно она является нормальной ссылкой Perl.

До выхода Perl версии 5 программистам в подобных случаях приходилось использовать eval:

eval "package Spackname; \$$val = \SSvarname"; # Задать Smai-nval die if S@;

Как видите, такой подход затрудняет построение строки. Кроме того, такой код работает относительно медленно. Впрочем, вам никогда не придется делать это лишь для того, чтобы косвенно обращаться к переменным по именам. Символические ссылки обеспечивают необходимый компромисс.

Функция eval также используется для определения функций во время выполнения программы. Предположим, вы хотите иметь возможность вычислять двоичные и десятичные логарифмы:

printf "1од2 of 100 is %.2f\n", log2(100); printf "loglO of 100 is %.2f\n", loglO(IOO);

В Perl существует функция log для вычисления натуральных логарифмов. Давайте посмотрим, как использовать eval для построения функций во время выполнения программы. Мы создадим функции с именами от 1од2 до 1од999;

Spackname = main; for (Si = 2; Si < 1000; Si++) { SlogN = log($i);



12.14. Применение h2ph для преобразования заголовочных файлов С 433

eval "sub ${packname}::logSl { log(shlft) / $logN }"; die if $@;

По крайней мере в данном случае это не нужно. Следующий фрагмент делает то же самое, но вместо того, чтобы компилировать новую функцию 998 раз, мы откомпилируем ее всего единожды в виде замыкания. Затем мы воспользуемся символическим разыменованием в таблице символов и присвоим одну и ту же ссылку на функцию по многим именам:

Spacknane = main;

for ($i =2; $i < 1000; $i++) {

my SlogN = log($i);

no strict refs;

•{"${packnane}::log$i"} = sub { log(shift) / $logN };

Присваивая ссылку тип-глобу, вы всего лишь создаете синоним для некоторого имени. На этом принципе построена работа Exporter. Первая строка следующего фрагмента вручную экспортирует имя функции Colors::blue в текущий пакет. Вторая строка назначает функцию main: :blue синонимом функции Colors: :azure.

*blue = \&Colors::blue;

«main::blue = \&Colors::azure;

Принимая BO внимание гибкость присваиваний тип-глобов и символических ссылок, полноценные конструкции eval "СТРОКА" почти всегда оказываются излишеством, последней надеждой отчаявшегося программиста. Ничего худшего себе и представить нельзя - разве что если бы они были недоступны.

t> Смотри также-

Раздел «Symbolic References» perlsub(i); рецепт 11.4

12.14. Применение h2ph для преобразования заголовочных файлов С

Проблема

Полученный от кого-то код выдает устрашающее сообщение об ошибке:

Cant locate sys/syscall.ph in §INC (did you run h2ph?) (§INC contains: /usr/llb/perl5/1686-liniJX/5.00404 /usr/llb/perl5 /usr/lib/perl5/site perl/i686-linux /usr/lib/perl5/site perl .) at some program line 7.

Вы хотите понять, что это значит и как справиться с ошибкой.

Решение

Попросите системного администратора выполнить следующую команду с правами привилегированного пользователя:



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