【问题标题】:D Templates: Coolest Hack [closed]D模板:最酷的黑客[关闭]
【发布时间】:2010-09-19 17:21:26
【问题描述】:

你用 D 编程语言做过或见过的最酷的有点实用元编程技巧是什么?有点实际的意思是排除编译时光线追踪器等。

【问题讨论】:

    标签: templates metaprogramming d


    【解决方案1】:

    An arbitrary precision type 它在编译时(在编译器之前)生成 ASM 代码

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

        【解决方案3】:

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

        【讨论】:

        • 只需要 7 分钟和 700MB 来编译一个 D 大小的语法(约 200 个作品)。 (完全披露,我写了 dparse)
        【解决方案4】:

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

        【讨论】:

          【解决方案5】:

          我最喜欢的是 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;
          }
          

          【讨论】:

            【解决方案6】:

            A united type template struct(它不会让你犯单位错误。)

            【讨论】:

              【解决方案7】:

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

              【讨论】:

                【解决方案8】:

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

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

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

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

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

                【讨论】:

                  【解决方案9】:

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

                  【讨论】:

                    【解决方案10】:

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

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

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

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

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


                    编辑:我发布的之前的代码链接相当可怕; this version is much more elegant.

                    【讨论】:

                    • 将代码发布到github并分享。好吧,如果你愿意的话。
                    • 感谢您的建议!是的,我确实想分享它。 :) 我从来没有听说过网站,但我刚刚注册了。不过,我对它的工作原理有点困惑……我是否需要创建密钥对和所有内容?还是我在网站的无关部分?
                    • 如果你想在自己的 repo 上做任何工作,你需要一个密钥对(我建议这样做)。但您也可以轻松创建一个要点:gist.github.com
                    • 酷!这是代码,如果有人感兴趣的话:gist.github.com/741782#file_memoize.d
                    • @StefanMajewsky:是的,我愿意,对此感到抱歉。 auto memoize(F)(F f) if (isCallable!(f)) { alias ParameterTypeTuple!(F) P; return delegate(P args) { static typeof(f(args))[Tuple!(F, P)] cache; auto key = tuple(f, args); return key in cache ? cache[key] : (cache[key] = f(args)); }; }
                    【解决方案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 进行无缝交互。 您可以使用单个命令注册整个类。

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 2010-10-24
                        • 1970-01-01
                        • 2010-09-21
                        • 2010-10-04
                        • 2011-04-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多