Анимация
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

print "How are you "; chomp($string = <STDIN>); If ($commands{$string}) {

$commands{$string}->(); } else {

print "No such command: $string\n";

Если вы создаете анонимную функцию, которая ссылается на лексическую (ту) переменную из вмещающей области действия, схема подсчета ссылок гарантирует, что память лексической переменной не будет освобождена при наличии ссылок на нее:

sub counter maker { my Sstart = 0; return sub {

return Sstart-n-;

# Замыкание

# Лексическая переменная

# из вмещающей области действия

Комментарий

Чтобы получить ссылку на функцию, достаточно снабдить ее имя префиксом \&. Кроме того, формулировка sub {} позволяет создавать анонимные функции. Ссылка на анонимную функцию может быть сохранена так же, как и любая другая.

В Perl 5.004 появилась постфиксная запись для разыменования ссылок на функции. Чтобы вызвать функцию но ссылке, раньше приходилось писать &$f uncname (@ARGS), где $f uncname - имя функции. Возможность сохранить имя функции в неременной осталась и сейчас;

$funcname = "thefunc"; &$funcname();

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

Во-вторых, оно не содержит данных о пакете, поэтому выполнение фрагмента в другом пакете может привести к вызову неверной функции. Наконец, если функция была в какой-то момент переопределена (хотя это происходит нечасто), символическая ссылка будет обращаться к текущему определению функции, а жесткая ссылка сохранит старое определение.

Вместо того чтобы сохранять имя функции в переменной, создайте ссылку на нее с помощью оператора \. Именно так следует сохранять функцию в переменной или передавать ее другой функции. Ссылки на именованные функции можно комбинировать со ссылками на анонимные функции;

ту %commancls = (

"happy" => \&]оу,

"sad" => \&sullen,

"done" => sub { die "See ya" },

"mad" => \&angry,



Scounter = counter maker();

for ($i =0; $1 < 5; $i ++) { print &$counter, "\n";

Даже несмотря на то что функция counter maker завершилась, а переменная $start вышла из области действия, Perl не освобождает ее, поскольку анонимная подпрограмма (на которую ссылается $counter) все еше содержит ссылку на Sstart. Если повторно вызвать counter maker, функция вернет ссылку на другую анонимную подпрограмму, использующую другое значение $start:

Scounterl = counter maker(); $count8r2 = counter maker();

for ($1 =0; $1 < 5; $i ++) { print &$counter1, "\n",

print &$counter1, " ", &$counter2, "\n",

Замыкания часто используются в косвенно-вызываемых функциях (callbacks). В графических интерфейсах и вообще в программировании, основанном на событиях, определенные фрагменты кода связываются с событиями нажатий клавиш, щелчков мышью, отображения окон и т. д. Этот код вызывается много позже, возможно, из совсем другой области действия. Переменные, используемые в замыкании, должны быть доступными к моменту вызова. Для нормальной работы они должны быть лексическими, а не глобальными.

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

sub timestamp {

my $start time = time();

return sub { return time() - $start time };

Searly = timestampO; sleep 20;

Slater = timestampO; sleep 10;

printf "Its been %d seconds since early.\n", Searly->(); printf "It s been %d seconds since later.\n", Slater->(); Its been 30 seconds since early. Its been 10 seconds since later.



Каждый вызов timestamp генерирует и возвращает новую функцию. Функция timestamp создает лексическую переменную $start time, которая содержит текущее время (в секундах с начала эпохи). При каждом вызове замыкания оно возвращает количество прошедших секу}1Д, которое определяется вычитанием начального времени из текущего.

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

Описание замыканий в рег е/(1); рецепты 10.11; 11.4.

11.5. Получение ссылок на скаляры

Проблема

Требуется создать ссылку на скалярную величину и работать с ней.

Решение

Для создания ссылки на скалярную величину воспользуйтесь оператором \:

$scalar ref = \$scalar; # Получение ссылки на именованный скаляр

Чтобы создать ссылку на анонимную скалярную величину (то есть скаляр, не являющийся неременной), присвойте }1уж1юе значение через разыменование нео-пределенной переменной;

undef $anon scalar ref; $$anon scalar ref = 15;

Ссылка на скалярную константу создается следующим образом; $anon scalar ref = \15;

Разыменование выполняется конструкцией ${...}:

print ${ $scalar ref }; # Разыменовать

${ $scalar ref } .= "string"; # Изменить значение субъекта

Комментарий

Если вам понадобилось создать Miioro новых анонимных скаляров, воспользуйтесь функцией, возвращающей ссылку на лексическую неременную вне области действия, как объяснялось во введении;

sub new anon scalar { my Stemp; return \$temp;

Perl почти никогда не выполняет косвенного разыменования. Исключение составляют ссылки на файловые манипуляторы, программные ссылки на sort и ссылочный аргумент функции bless. Из-за этого для разыменования скалярной переменной следует снабдить ее префиксом $, чтобы получить все ее содержимое:

$sref = new anon scalar(); $$sref = 3;

print "Three = $$sref\n";



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