LINUX.ORG.RU

perl, my


0

0

Код:
goto a;
b: print($str);
goto end;
a: my $str = "hello";
goto b;
end:;

если его выполнить, то ничего не выведется. 
Если my убрать, то всё будет работать как надо. 
Можно ли как то сделать, чтобы при использовании my всё работало так же.
Контроль не нужен, код выполняется при no use 'vars';

PS этот код генерируется из шаблона, и на его, кроме интерпретатора,
никто не видит, поэтому goto никому не мешает.
★★★★★

Не ясна постановка задачи. Что можно менять, шаблон? Если честно, то в данном случае, не зная специфики задачи, можно посоветовать
не использовать my и strict. Хотя это конечно "плохой стиль". Как вариант:

my %VARS;
goto a;
b: print($VARS{$str});
goto end;
a: $VARS{$str} = "hello";
goto b;
end:;

Casus ★★★★★
()
Ответ на: комментарий от Casus

Ещё возможно, что тебе local вместо my подойдёт, хотя постановка задачи действительно не ясна.

Teak ★★★★★
()

Попробую пояснить. Есть шаблон (вроде HTML::Mason). Его надо преобразовать в перл-код, который выводит то, что надо. Например
a = <% $a %> преобразовать в что-то вроде print('a = ', $a);
В шаблоне есть т.н. init-блоки. Они могут быть где угодно, но должны исполняться первыми. Например
<% $a %>
<%init $a = "hello"; %>

я реализовал это с помощью нехитрой системы goto-в.
Например вышеприведённый код транслируется в

goto _i0;_r0:print('',$a ,'
');goto _r1;_i0:;$a = "hello"; ;goto _i1;_r1:print('
');goto _r2;_i1:goto _r0;_r2:;

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

Собственно здесь и возникает поставленная проблема. Пользователь вполне может захотеть писать код
<% $a %>
...
<%init
my $a = "hello";
%>
Который преобразовывается в код, подобный тому, который я показал в первом сообщении, и не работает. Запрещать использование my не хочется.

И вообще интересно было бы узнать, почему это происходит. Я думал, что my влияет лишь на то, чтобы при включенном use strict; обозначать используемые переменные, и используется на этапе компиляции, но оказывается это не так.

Legioner ★★★★★
() автор топика
Ответ на: комментарий от Legioner

> И вообще интересно было бы узнать, почему это происходит.


Ужыс. Происходит это совершенно очевидно почему, если не полениться прочитать документацию. my объявляет локальную переменную, область видимости которой начинается с момента объявления. У тебя в тексте print $str стоит _до_ объявления. Я не знаю особенностей HTML::Mason. Если блоки BEGIN исполняются там всегда, а не как в mod_perl, то даю наводку:

$ perl -le 'BEGIN { print 2; } print 4; BEGIN {print 5; }'
2
5
4

Casus ★★★★★
()
Ответ на: комментарий от Legioner

> ... Запрещать использование my не хочется.

А придётся. Или как минимум все использования my перед генерацией кода надо будет преобразовать во что-то другое. Проще просто убрать. Или переупорядочить код, все init-блоки вынести в начало.

Casus ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.