Как работает 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? Это так? Есть ли техническая причина для этого?
2 ответа
Вы не можете создавать постоянные массивы, потому что массивы не являются данными. Perl 5 имеет пять типов данных (вещи, которые можно хранить в переменных):
- нет значения (undef)
- чисел
- строки
- Рекомендации
- списки (составленные из одного или нескольких предыдущих типов)
Вы можете сделать константу из любого из них. Perl 5 также имеет три контейнера:
- скаляр
- массив
- гашиш
Скаляры могут содержать любой из первых четырех типов данных, массивы и хэши могут содержать списки. Важно не путать вещи, которые содержат данные и сами данные.
Что касается B::Deparse
после создания он сбрасывает optree, поэтому он покажет результаты всего постоянного свертывания.
Я пока недостаточно об этом думал, но не вижу очевидных причин, по которым его нельзя было сложить.
Вы не можете создать константный массив в Perl, во внутренних органах нет ничего, что указывало бы на константный массив, хеш или даже скаляр. "use constant" использует способность Perl встроить подпрограммы с прототипом ()
и простой код. Лучшее, что вы можете сделать, это установить флаг readonly, но его можно отключить во время выполнения.
Perl может использовать флаг readonly во время компиляции в качестве подсказки, чтобы указать, что массив действительно только для чтения, и затем встроить любой доступ, используя постоянный индекс. Такая эвристика, вероятно, была бы безопасной, поскольку флаг readonly не должен быть доступен пользователю, и вам, вероятно, не следует его сбрасывать.