Примеры того, какие шаблоны Ds можно использовать для
Я слышал, что язык D обладает мощными функциями метапрограммирования для выполнения функций во время компиляции. Это звучит очень интересно, но мне трудно думать о практических примерах вещей, которые трудно выполнить без них.
Может ли кто-нибудь привести примеры ситуаций, когда функции метапрограммирования D очень удобны?
Ответы
Ответ 1
Если вы хотите, чтобы практические примеры того, как использовать средства метапрограммирования D (CTFE, или оценка времени компиляции, являются лишь одним из них, а не даже самым важным), выглядят не дальше, чем в стандартной библиотеке Dobos. Большая часть этого кода написана Андреем Александреску, который изобрел множество методов метапрограммирования шаблонов на С++ и теперь работает с Уолтером Брайтом по дизайну и реализации D.
Лучшие модули для просмотра - std.range
и std.algorithm
. Они почти полностью состоят из шаблонов, были спроектированы Андреем и удивительно читаемы, учитывая количество метапрограммирования, которое они используют. Я внес значительный вклад в оба этих модуля и прочитал код, который был там, когда я начал, в основном, как я узнал.
Весь код лицензируется в соответствии с (чрезвычайно разрешительной) лицензией Boost и может быть просмотрен непосредственно из вашего браузера на сайте Phobos Trac на dsource.org.
Чтобы дать вам дорожную карту того, что вы смотрите, D средства метапрограммирования в основном делятся на 4 категории:
-
Шаблоны, которые в основном похожи на шаблоны С++, но с некоторыми дополнительными функциями, такими как static if
, static assert
, вариативные шаблоны и ограничения, которые в основном похожи на концепции, но более простые.
-
Отображение времени/интроспекция времени компиляции. Сюда входят встроенные выражения is()
и __traits
, а также стандартный библиотечный модуль std.traits.
-
Примеси. Они позволяют использовать шаблон (шаблоны mixins) или строку времени компиляции (string mixins) и оценивать ее как код в текущей области. String mixins можно рассматривать как нечто вроде выражения eval, за исключением того, что строка оценивается как код во время компиляции, а не во время выполнения.
-
Оценка функции времени компиляции или CTFE, которая позволяет выполнять функции, которые удовлетворяют определенным критериям, которые будут оцениваться во время компиляции. Одним из важных применений CTFE является то, что в сочетании со строковыми миксинами вы можете генерировать код как строку во время компиляции, а затем оценивать его как код в области, где выполняется оператор mixin
. Для примера см. Std.range.Lockstep и std.range.OutputRangeObject, который я недавно проверил в релизах SVN для Phobos.
Ответ 2
Одним из самых крутых и практичных способов использования функции времени компиляции является генерация кода во время компиляции, возможно, из файлов конфигурации или, возможно, скриптов.
Вот простой пример обработки файла во время компиляции.
main.d
string make_ints(string s)
{
string ret = "";
foreach (varname; split(s))
ret ~= "int " ~ varname ~ "; ";
return ret;
}
void main()
{
mixin(make_ints(import("script")));
foo = 1;
bar = 2;
xyz = 3;
}
script
foo bar xyz
Во время компиляции файл "script" будет считываться, разбиваться на пробелы, а затем make_ints возвращает int foo; int bar; int xyz;
непосредственно в D-код, готовый для использования этих переменных.
Пока это бесполезный пример, вы можете легко увидеть, как это можно использовать для чтения значений из файла конфигурации (возможно, значения для размера кеша или что-то в этом роде). Игры могут использовать это, чтобы генерировать исходный код D из сценариев, что будет отлично подходит для производительности (как правило, игры прибегают к использованию интерпретируемого кода для сценариев и страдают от производительности).
Вы также можете использовать это для автоматической настройки производительности. Скажем, у вас есть постоянный X, который можно настроить, чтобы повлиять на производительность различными способами, но вы не знаете, какое значение X даст вам лучшую производительность. Вы можете поместить X в файл, прочитать его во время компиляции для использования, попробовать другие значения во время выполнения и перенести лучший из них в файл. Таким образом, вы постепенно улучшаете производительность, не делая ничего вручную.
Ответ 3
Я не хорошо разбираюсь в метапрограммах. Вот мой взгляд на три основные конструкции, найденные в D.
- Оценка функции времени компиляции - это производительность. Создание компилятора делает как можно больше работы, так что меньше делается после запуска программы.
- Как и создание кеша простых чисел, если вы его часто используете, используйте.
- Шаблоны относятся к устранению дублирования алгоритма. Это не просто общее программирование, но поскольку D имеет CTFE, он не нужен в тех же случаях, что и С++.
- Mixins - это возможность генерировать код во время компиляции, которое добавляется в программу. Он опирается на такие вещи, как шаблоны и CTFE, но все же важный элемент, не предоставленный другими.
Ответ 4
Практически интересное его использование, которое я знаю, это библиотека, которую я написал *
для использования проверки типа для обеспечения безопасности устройства ( что запрещает добавлять расстояния до времени и обеспечивает правильное преобразование при добавлении метров в футы). То же самое можно сделать и было сделано на С++, но делать это в D во время компиляции немного сложнее, чем было бы делать это во время выполнения.
*
извините за бесстыдный плагин.