22

你用 D 编程语言做过或见过的最酷的、实用的元编程技巧是什么?有点实用意味着排除,例如,编译时光线追踪器。

4

12 回答 12

9

任意精度类型它在编译时生成 ASM 代码(在编译器之前)

于 2008-11-04T18:45:54.193 回答
8

Scrapple 工具中的 DParse 是一个模板化的解析器生成器。然而,ldc 是唯一一个具有正常运行的编译时 GC 的 D 编译器(但即便如此,它也有一些奇怪的随机崩溃)。我玩了一点,你可以做一些有趣的事情,比如配置文件解析和其他东西,但是在编译时 GC 完全运行之前你不能做大事。

于 2008-10-29T17:40:25.737 回答
8

在最酷的方面,我不得不说 Kirk McDonald 的PyD(和其他类似的绑定),因为它们在检测和处理许多不同的类型以及复杂的代码生成方面做了大量的工作。

也就是说,PyD 之所以获胜,是因为BLADE在技术上使用的是 CTFE,而不是模板。

就个人而言,D 模板已在我的一个研究项目中得到广泛使用。这是一个模拟框架,模块可以在其中定义自己的私有数据类型。向框架公开一个新的用户类型需要一行代码,它为该类型以及相关的网络序列化/反序列化代码创建一个 XML 解析器。

于 2009-04-01T10:44:28.443 回答
7

D/Objective-C 桥使用模板让您在 D 中操作 Cocoa 对象。

于 2008-10-29T03:49:23.527 回答
6

我最喜欢的是来自 tools.base 的 ElemType 和 KeyType:

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;
}
于 2008-10-29T17:51:21.223 回答
6

编译时字符串散列。您可以使用它来混淆代码中的嵌入字符串。只需搜索“哈希”。该页面上还有很多其他有趣的示例。

于 2008-10-30T15:00:21.037 回答
6

一个统一类型的模板结构(它不会让你犯单元错误。)

于 2008-11-04T18:44:15.803 回答
6

一个例子是D 标准库中的位域工具,它为从用户指定的布局开始的位域操作生成代码。

Tuple 设施是另一个例子。它根据用户提供的类型和可选名称生成一个元组。除了注入命名字段之外,没有很多生成性的umph,但我认为这是一个说明性的例子。

在不知道 Lambert 的漏洞利用的情况下,我只是将 memoize 添加到标准库中 - 请参阅此处的文档,此处的代码,以及相关新闻组讨论。

我研究的另一个工具是一个高阶函数,它将积分或实值函数制成表格(例如提供快速指数)。那还没有准备好发布。

一旦在编译期间允许创建对象,将很容易创建例如在编译期间执行所有自动机生成的正则表达式引擎。

于 2011-01-04T14:00:34.453 回答
5

我会回答我自己的问题,因为当我问这个问题时,这个问题并不存在。我为垃圾收集器写了一个补丁,它使用模板和编译时自省来为任意复杂的用户定义类型生成指针偏移信息,以允许精确的堆扫描,而不是在编译器中完成。

于 2010-02-09T03:49:41.273 回答
4

我写了一个 memoize() 函数,它的头是这样的(代码有点长,粘贴在这里):

自动记忆(TFunc)(TFunc func);

它的作用是,你给它一个函数的地址,它返回一个强类型的委托(与原始函数相同的签名和返回类型)缓存原始函数的返回值,以便使用相同的参数调用它两次只调用底层函数一次。例如,这是一个以线性而非指数时间执行的斐波那契数列的记忆化“递归”定义:

uint fib(uint n) { 返回 n > 0 ?n > 1 ? 记忆(&fib)(n - 1)+记忆(&fib)(n - 2):1:0;}

可以正常调用,如:fib(1000);


编辑:我发布的前一个代码的链接相当可怕;这个版本要优雅得多

于 2010-12-14T09:51:34.870 回答
2

用于从Stream对象读取和写入简单结构的Mixins:

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);
于 2011-01-04T15:52:22.490 回答
2

LuaD还广泛使用元编程与 Lua 无缝交互。您可以使用单个命令注册整个类。

于 2011-02-03T09:53:51.297 回答