| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Perl: Общие вопросы > Объявление и инициализация в цикле |
| Автор: ginnie 20.3.2008, 14:54 | ||
| Уважаемые коллеги! Извините за "детский" вопрос, но хочу для себя прояснить как работает объявление и инициализация внутри цикла:
На каждой итерации происходит только присвоение переменной $test нового значения, или что-то большее? Очень приветствуется ссылка на документацию! |
| Автор: GoDleSS 20.3.2008, 15:45 | ||
| Для начала perldoc -f my Функция my объявляет переменную локальной для текущего блока. Таким образом переменная, описанная my внутри цикла будет каждый раз "создаваться" по новой, а старые участки памяти будут стираться, за исключением случаев, когда на них уже что-либо ссылается. Таким образом код
выведет 14..23 |
| Автор: amg 20.3.2008, 15:51 | ||
А вот такой дурацкий код что напечатает? Можете сказать, не проверяя? (Я бы не угадал
|
| Автор: BlackLFL 20.3.2008, 16:01 |
| такой код в обще не должен дать результат, т.к. переменная $test не объявлена до инициализации. |
| Автор: KSURi 20.3.2008, 16:01 | ||
То, что написал GoDleSS - логично, я всегда так и считал. Но вот сейчас начал сомневаться:
Меня смущает, что у всех $test один адрес в памяти. Если переменная каждый раз создается снова, то почему адрес всегда одинаковый? |
| Автор: ginnie 20.3.2008, 16:06 | ||||
| Уважаемый GoDleSS, на чем основана уверенность, что будет создаваться новая переменная? Спасибо за то, что навели на верную мысль! код
выводит
|
| Автор: BlackLFL 20.3.2008, 16:09 | ||||
2ginnie, не успел запостить, я тоже провел аналогичный тест
|
| Автор: ginnie 20.3.2008, 16:09 |
| BlackLFL, почему не объявлена? Какая часть присваивания выполняется сначала левая или правая? |
| Автор: BlackLFL 20.3.2008, 16:14 | ||||
тут это не имеет значения, Perl все-равно выдаст ошибку
|
| Автор: amg 20.3.2008, 16:19 |
| С use strict - безусловно. А без него? |
| Автор: BlackLFL 20.3.2008, 16:43 | ||
правый конечно |
| Автор: amg 20.3.2008, 16:51 |
| Что-то я понимаю, нифига не понимаю. И по поводу переменной с my в цикле (вроде, каждый раз должна новая пременная создаваться, по крайней мере, работает, как будто так оно и есть, но так ли на самом деле ?). И с тем своим дурацким кодом тоже не вполне ясно, в какой последовательности операции выполняются. Добавлено через 4 минуты и 20 секунд BlackLFL, но если сначала выполняется правая часть (я тоже в этом был уверен), то почему переменная в левой части оказывается неопределенной? |
| Автор: BlackLFL 20.3.2008, 17:06 |
| amg, кстати да ... интересно получается ... Добавлено @ 17:10 мне так кажется, что my имеет какое-то волшебное умение применять undef ... а сам интерпретатор, лишь "опирается" на my, для создания таблицы имен ... |
| Автор: ginnie 20.3.2008, 17:42 | ||||
| amg, похоже на то, что локальная переменная становится видна (кроме непосредственного присваивания) в коде только начиная со следующей команды (после ';') в коде программы. Например, в коде
получаем Global symbol "$test" requires explicit package name в строке с условием По поводу цикла показателен следующий пример
Переменная создается один раз в области видимости, но при каждой итерации ей присваивается значение undef. |
| Автор: ginnie 20.3.2008, 18:02 | ||||
Дальнейшие исследования показали, что в коде
получаем результат
т.е. присваивание в цикле проиводится переменной $test, определенной выше цикла. |
| Автор: GoDleSS 20.3.2008, 18:23 | ||||||
Сторонние мануалы, проверил,
признаю свою неправоту по данному пункту Не перевыделение, а перезаполнение одной и той же области памяти - явный плюс в сторону перлы! Вообще исследование получается интересным, хоть и отрывает от работы ) |
| Автор: ginnie 20.3.2008, 18:31 | ||
| Уважаемые коллеги, спасибо за помощь! Для себя из обсуждения вынес следующее: 1. Локальная переменная внутри цикла создается на первой итерации. На каждой итерации в этом месте ей присваивается значение undef. 2. В perlsub в разделе Private Variables via my() написано
что приводит к разным нетривиальным последствиям (примеры приведены выше). 3. При использовании переменной внутри цикла до строки объявления приводит к использованию одноименной переменной, определенной выше области видимости цикла на любой итерации. |
| Автор: GoDleSS 21.3.2008, 14:30 | ||
Еще одно маленькое исследование
link SCALAR(0x18329f0) value 2 link SCALAR(0x226060) value 3 link SCALAR(0x225e8c) value 4 link SCALAR(0x1832984) value 5 link SCALAR(0x1832b70) value 6 link SCALAR(0x1832b88) value 7 link SCALAR(0x1832ba0) value 8 link SCALAR(0x1832bb8) value 9 link SCALAR(0x1832bd0) value 10 link SCALAR(0x1832be8) value 11 показало, что если на локальную переменную сохраняется ссылка, то память под нее таки выделяется по новой. Perl умный однако Далее замечается один момент: увеличение адреса статично - 24 байта/шаг выделяется сегмент под одну переменную + под 1 элемент массива и того получается, что перла изначально выделяет под скаляр 12 байт |
| Автор: ginnie 21.3.2008, 14:57 | ||
| GoDleSS, спасибо за важное дополнение! А вот за
надо по рукам надавать |
| Автор: GoDleSS 21.3.2008, 15:06 | ||
Это почему же, позвольте полюбопытствовать? 0_о Часто пользуюсь похожими конструкциями и не вижу в них ничего плохого. |
| Автор: ginnie 21.3.2008, 15:17 | ||
Нигде не встречал рекомендаций по добавлению нового элемента в массив путем инкремента номера последнего элемента этого массива:
Можно ссылку на документацию по поводу ++$#array? |
| Автор: GoDleSS 21.3.2008, 16:02 | ||
Пока конструкция на ура, взял его из каких-то готовых решений очень давно использую на ряду с push(@array, LIST); и не вижу явных минусов, за исключением разве что соображения: "Зачем понижать читабельность кода, используя и push, и ++$#array Но это уже все слишком далеко от темы ;) |
| Автор: ginnie 21.3.2008, 16:10 | ||
GoDleSS, если не сложно, расскажите, как работает конструкция
|
| Автор: GoDleSS 21.3.2008, 16:20 |
| $#array содержит индекс последнего элемента массива если мы говорим $#array=-1; все элементы удаляются (индекс всегда >=0), аналогично @array=(); если мы говорим $#array++ индекс последнего элемента увеличивается на еденицу, но после передачи значения индекса, поэтому $array[$#array++] = expr; приведет к переопределению текущего последнего элемента и созданию нового со значением undef выражение ++$#array увеличит индекс последнего с передачей индекса до выполнения, поэтому $array[++$#array] = expr; банальный аналог push(@array, expr); при условии, что expr - скаляр Надеюсь, что более или менее доступно изложил мысль |
| Автор: KSURi 21.3.2008, 17:01 |
Я вообще думал, что $#arr - readonly oO Спасибо, буду знать, хотя не знаю зачем) |