Какой самый классный несколько практичный метапрограммирующий взлом, который вы сделали или видели на языке программирования D? Несколько практических средств, исключающих, например, raytracer для компиляции.
D шаблоны: самый крутой взлом
Ответ 1
В терминах самого крутого, я должен был бы сказать Kirk McDonald PyD (и другие аналогичные привязки), поскольку они выполняют огромную работу по обнаружению и обработке множества разных типов, а также к сложной генерации кода.
Тем не менее, PyD выигрывает только потому, что BLADE технически использует CTFE, а не шаблоны.
В более личном примечании, D-шаблоны широко используются в моем исследовательском проекте. Это симуляционная структура, в которой модули могут определять свои собственные частные типы данных. Для отображения нового типа пользователя в фреймворке требуется одна строка кода, которая создает синтаксический анализатор XML для этого типа, а также соответствующий код сериализации/десериализации сети.
Ответ 2
Произвольный тип точности Он генерирует код ASM во время компиляции (до компилятора)
Ответ 3
Инструменты DParse в Scrapple - это шаблонный генератор парсера. Тем не менее, ldc является единственным компилятором D с функциональным временем компиляции GC (но даже тогда он имеет несколько случайных случайных сбоев). Я немного поиграл с ним, и вы можете сделать некоторые интересные вещи, такие как синтаксический анализ конфигурационных файлов и прочее, но до тех пор, пока GC GC компиляции не будет полностью запущен, вы не сможете делать большие вещи.
Ответ 4
D/ Objective-C Bridge использует шаблоны, чтобы вы могли манипулировать объектами Cocoa в D.
Ответ 5
Моими фаворитами будут ElemType и KeyType из tools.base:
template ElemType(T) {
alias typeof((function() {
foreach (elem; Init!(T)) return elem; assert(false);
})()) ElemType;
}
template KeyType(T) {
alias typeof((function() {
foreach (key, elem; Init!(T)) return key; assert(false);
})()) KeyType;
}
Ответ 6
Компиляция хэширования строки времени. Вы можете использовать это для обфускации встроенных строк в свой код. Просто найдите "хэш". довольно много других интересных образцов на этой странице.
Ответ 7
A структура шаблона с объединенным типом (он не позволит вам создавать ошибки блока.)
Ответ 8
Одним из примеров является bitfields в стандартной библиотеке D, которая генерирует код для манипуляции с полем бит, начиная с пользовательского макета.
объект Tuple - еще один пример. Он генерирует кортеж на основе пользовательских типов и дополнительных имен. Существует не так много генеративных umph там, кроме как для ввода именованных полей, но я считаю это иллюстративным примером.
Не зная о эксплойте Ламберта, я просто добавил memoize в стандартную библиотеку - см. здесь для документации, здесь для кода и здесь для соответствующего обсуждения в группе новостей.
Другим объектом, над которым я работал, является функция более высокого порядка, которая отображает интегральную или вещественнозначную функцию (например, предлагает быструю экспоненту). Это еще не готово к выпуску.
Как только создание объекта будет разрешено во время компиляции, его будет легко создать, например. двигатели регулярных выражений, которые генерируют все автоматы во время компиляции.
Ответ 9
Я отвечу на свой вопрос, потому что этого не было, когда я спросил его. Я написал патч сборщику мусора, который использует шаблоны и интроспекцию времени компиляции, чтобы генерировать информацию смещения указателя для произвольно сложных пользовательских типов, чтобы обеспечить точное сканирование кучи вместо того, чтобы это было сделано внутри компилятора.
Ответ 10
Я написал функцию memoize(), чей заголовок это (код немного длинный для вставки здесь):
auto memoize (TFunc) (TFunc func);
Что он делает, вы даете ему адрес функции, и он возвращает строго типизированный делегат (тот же тип сигнатуры и возвращаемого типа, что и исходная функция), который кэширует возвращаемые значения исходной функции, так что вызов ее дважды с один и тот же параметр только один раз вызывает базовую функцию. Например, это мемуаризованное "рекурсивное" определение последовательности Фибоначчи, которое выполняется в линейном, а не экспоненциальном времени:
uint fib (uint n) {return n > 0? n > 1? memoize (& fib) (n - 1) + memoize (& fib) (n - 2): 1: 0; }
Вы можете назвать это нормально, как в: fib (1000);
Изменить: предыдущий код, ссылка которого я разместил, была довольно отвратительной; эта версия намного более элегантна.
Ответ 11
Миксины для чтения и записи простых структур из объекта Stream:
template TStructReader() {
private alias typeof(*this) T;
static T opCall(Stream stream) {
assert(stream.readable);
T ret; stream.readExact(&ret, T.sizeof);
return ret;
}
}
template TStructWriter() {
private alias typeof(*this) T;
void write(Stream stream) {
assert(stream.writeable);
stream.writeExact(this, T.sizeof);
}
}
Используйте его следующим образом:
align (1) struct MyStruct {
... definitions here ...
mixin TStructReader;
mixin TStructWriter;
}
auto ms = MyStruct(stream);
ms.write(stream);
Ответ 12
LuaD также широко использует метапрограммирование для бесшовного взаимодействия с Lua. Вы можете зарегистрировать весь класс с помощью одной команды.