Как работает O=Deparse и есть ли в Perl константные массивы?

Мне интересно, показывает ли -MO=Deparse все оптимизации Perl, и почему это не свернуто в Perl 5.10?

$ perl -MO=Deparse -e'[qw/foo bar baz/]->[0]'
['foo', 'bar', 'baz']->[0];
-e syntax OK

Кое-кто в IRC подумал, что O=Deparse, возможно, не показывает все, но определенно показывает некоторые постоянные свертывания.

$ perl -MO=Deparse -e'use constant "foo" => "bar"; foo'
use constant ('foo', 'bar');
'???';
-e syntax OK

Тот же результат, если я явно пишу константу sub. Хотя это и предсказуемо, довольно интересно, что в документации в constant.pm вы создаете список констант, а не массив констант. Я предполагаю, что это не только не свернуто, как скалярные константы, но и требует накладных расходов на создание нового массива при каждом вызове.

$ perl -MO=Deparse -e'use constant foo => qw/foo bar baz/; (foo)[0]'
use constant ('foo', ('foo', 'bar', 'baz'));
(foo)[0];
-e syntax OK

Единственный вывод, к которому я могу прийти, это то, что -MO=Deparse показывает все свертки, а константные массивы просто не оптимизированы в Perl? Это так? Есть ли для этого техническая причина?


person Evan Carroll    schedule 24.08.2010    source источник
comment
Я все еще в замешательстве, почему меня минусуют за это? Кто-нибудь, напишите мне. Не потому ли, что вопрос слишком эзотерический? Вы полагаете, что это повлечет за собой много работы ради какой-либо выгоды? Я просто спросил, можно ли это сделать и почему это не делается. основной ответ, похоже, отвечает на те же вопросы, что и я. (1) Предположим, что это невозможно сделать по техническим причинам (2) затем предположим, что это просто не делается, (3) затем предположим, что это не сделано, потому что это не имеет достаточного значения.   -  person Evan Carroll    schedule 25.08.2010


Ответы (2)


Вы не можете создавать константные массивы, потому что массивы не являются данными. В Perl 5 есть пять типов данных (вещи, которые можно хранить в переменных):

  • нет значения (undef)
  • числа
  • струны
  • Рекомендации
  • списки (состоящие из одного или нескольких предыдущих типов)

Вы можете сделать константу из любого из них. Perl 5 также имеет три контейнера:

  • Скаляр
  • Множество
  • Хэш

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

Что касается B::Deparse, он выгружает оптодерево после его построения, поэтому он покажет результаты всех постоянных складок.

Я еще мало думал об этом, но не вижу явных причин, по которым его нельзя было бы свернуть.

person Chas. Owens    schedule 24.08.2010
comment
Не могли бы вы объяснить -MO=Deparse -e'use strict; print {}->[1] против use strict; print {}->[1]. В какой-то момент strict узнает, что вы пытаетесь получить недопустимую ссылку для N-го элемента (т. е. что {} является хэш-ссылкой). Я знаю, что мы часто говорим, что строгие состояния работают во время компиляции. Откуда strict знает, какой это тип ссылки? Не могли бы вы объяснить немного больше в этом направлении? - person Evan Carroll; 25.08.2010
comment
@Evan Carroll Эван Кэрролл Строгая прагма этого не улавливает, она заботится только об объявлении переменных ("vars"), запрете символических ссылок ("refs") и запрете большинства строк пустого слова ("subs"). Оператор -> разыменовывается во время выполнения, поэтому до тех пор мы не получаем ошибку. Если бы мы заставили -> выполнять свертывание констант, мы, вероятно, могли бы поймать эту конкретную ошибку во время компиляции. - person Chas. Owens; 25.08.2010
comment
Эмпирическое правило всегда заключалось в том, что strict не замедляет время выполнения. Вещи, которые сделали это, были зарезервированы для warnings.pm. Таким образом, strict выполняет проход по дереву операций во время выполнения во время BEGIN{} и выдает исключение, или strict утверждает, что reftype действителен за счет скорости во время выполнения? -- Или я до сих пор не понимаю. - person Evan Carroll; 25.08.2010
comment
Прагма strict не может замедлить время выполнения (если только ваша среда выполнения не содержит новое время компиляции через строку eval). Все его эффекты находятся во время компиляции. Я считаю, что strict запускается по мере создания оптического дерева, а не после. Вы также до сих пор не понимаете насчёт strict. Это ошибка времени выполнения Perl 5 и не имеет ничего общего с strict или warnings. Аналог perl -e '$x=$y=0; $x/$y'. - person Chas. Owens; 25.08.2010
comment
вы совершенно правы, ekk perl -e'die; print {}->[1]' это утверждение времени выполнения, которое улавливает это. - person Evan Carroll; 25.08.2010
comment
Я хотел бы отметить, что я еще не готов принять этот ответ, потому что из вашего обновления кажется, что вы можете быть убежден, что его можно сложить, но все еще нет. Я хотел бы еще знать, почему это может быть, по вашему мнению, и какие причины могут помешать этому быть. - person Evan Carroll; 25.08.2010
comment
@ Эван Кэрролл Я думал об этом некоторое время и не вижу причин, по которым его нельзя было бы сложить. Я предполагаю, что причина, по которой он еще не был оптимизирован, заключается в том, что код, подобный [qw/a b c/]->[0], встречается редко, но код, подобный 24 * 60 * 60, встречается часто. - person Chas. Owens; 25.08.2010

Вы не можете создать постоянный массив в Perl, во внутренностях нет ничего, что указывало бы на постоянный массив, хэш или даже скаляр. «использовать константу» использует способность Perl встраивать подпрограммы с прототипом () и простым кодом. Лучшее, что вы можете сделать, это установить флаг только для чтения, но его можно отключить во время выполнения.

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

person Schwern    schedule 24.08.2010
comment
..и если вы это сделаете, вы заслуживаете того, что получаете :) - person Ether; 28.08.2010