代码之家  ›  专栏  ›  技术社区  ›  Wayne Werner

元编程有什么用?

  •  68
  • Wayne Werner  · 技术社区  · 16 年前

    我读过:

    我承认元编程/代码生成背后的目的有些混乱。

    有没有人有一个具体的例子来说明他们在哪里使用元编程/代码生成?更好的解释是为什么它比另一个更好。

    编辑 : Thistle 可以考虑元编程吗?

    10 回复  |  直到 16 年前
        1
  •  115
  •   Benoît photo_tom    16 年前

    想象一下一个造汽车的人。假设这和使用电脑是一样的。

    所以他建工厂来造汽车,这样好多了。他现在正在编程!
    然而,在某种程度上,他又一次意识到自己总是在做同样的事情。

    元编程是非常强大的,但系统中的一个小故障使所有的优势变成了巨大的困难。所以掌握并使用它。。。或者离远点!

        2
  •  20
  •   Ira Baxter    13 年前

    我认为元编程是“编写(或修改)其他程序的程序”。 (另一个答案是“制造工厂的工厂”,很好的比喻)。

    正交设计问题(“方面”)。。。

    值得一提的是,有多少不同的机制被发明来实现这一点: 这种能力的分散分布意味着你可以做一些 一种语言中的各种元编程,有一定的局限性,但却不能在另一种语言中实现这些类型的元编程。这太让人恼火了:-}

    使用 任何 program transformations . 这 语法,替换为 那个

    一般来说,一个转变本身并不令人印象深刻,但几十个或几百个转变都能让人印象深刻 代码的惊人变化。因为(复杂的)程序转换可以 效果模拟一个图灵机,可以进行任意代码修改,包括 你发现的所有这些点式技巧都是散乱的。

    应用这些转换的另一个方法是 元 -元编程工具: 写“写程序的程序”的程序。

    任意代码。而且,你不需要语言设计委员会来意识到 所以你今天可以继续工作。

    一个有趣的教训是,这样的机器需要强大的程序分析(symbol) 表、控制和数据流分析等) 方面的切入点规范,即“在看起来像这样的地方进行更改”)。

    我们使用了“元”元编程工具( DMS Software Reengineering Toolkit )在…上进行下列活动 大的 代码库自动:

    • 语言迁移
    • 实现测试覆盖率和探查器
    • 大规模架构重组
    • 工厂控制代码生成
    • 嵌入式网络控制器的实现
    • 逆向工程的代码回到概念

    跨语言,包括java,C++,C++,PHP,…

    答案与规模、时间和准确性有关。

    或者是手工进行分析或修改的时候。

    对于代码生成或优化任务,您可以 它是手工完成的,但是工具可以更快更准确地完成。

    本质上,这些工具做了人类根本做不到的事情。

    值得注意的是,这些工具没有创造性;你还在吗 任务是什么(参见上面的示例列表)并确定 如何定义实现效果的分析/转换。 你还需要 元

        3
  •  5
  •   Georg Fritzsche    16 年前

    我从元编程中得到了最大的好处,可以在不同的api之间架桥。

    一个有效的例子就是火呼吸 JSAPIAuto 这样就可以简化编写给JavaScript的C++类。通过为要被曝光的函数提供注册工具,可以检查参数类型,并从编译时生成的拟合代码转换为脚本,以将脚本API类型转换为本机C++类型,甚至直接支持。 map vector

    作为一个简单的例子,考虑一个暴露的 add(a, b) 使用某些脚本API类型的函数:

    ScriptVariant add(const std::vector<ScriptVariant>& values) {
        // have to check argument count
        if(values.size() != 2)
            throw script_error("wrong number of arguments");
    
        try {
            // have to convert from scripting-API types
            long a = values[0].convert_cast<long>();
            long b = values[0].convert_cast<long>();
            return a+b; // potentially need to convert back too
        } catch(ScriptVariant::bad_cast& e) {
            // need to handle conversion failure
            throw script_error("conversion failed :(");
        }
    }
    

    实际的逻辑只有一行,检查和转换是烦人和冗余的。使用前面提到的注册设施(例如在建造商中):

    registerMethod("add", make_method(this, &MyClass::add));
    

    现在可以简单地写为:

    long add(long a, long b) {
        return a+b;
    }
    

        4
  •  3
  •   Community Mohan Dere    9 年前

    我最近(过去6个月)代码生成的具体示例:

    1. 我曾经得到一个电子表格,将XSD中的元素映射到数据库中的表列。可以使用宏和VBA从电子表格生成XSL片段和完成查询。这些片段和查询被复制并粘贴到执行它们并处理结果的系统中(大部分是原样的,无需进行任何更改)。这不是一个很好的解决方案,但它确实让一个非常乏味的工作变得不那么乏味,而且产生的代码看起来可能比我花一两周的时间手工编写的代码要一致得多。

    What are the coolest examples of metaprogramming that you've seen in C++?

        5
  •  3
  •   Rui Curado    16 年前

    我可以举我自己的具体例子:我正在发展 ABSE ,这是一种元编程方法。使用ABSE可以创建一个模型(实际上是一个树),其中每个项都是一个“原子”。这个原子表示一个“概念”,包含定义它所必需的元数据。

    然后,主机建模器( AtomWeaver ,与ABSE一起开发)将模型和它的所有原子“编织”出一个生成器程序。然后运行该程序,生成所需的工件(源代码、数据等)。

    因此,ABSE工作流程是:

    1. 创建一个离散概念(元程序的一部分)
    2. 在模型中重用该概念(有效地构建元程序)

    乍一看,这看起来像是许多冗余的、复杂的工作,但如果你掌握了这个概念,它实际上是相当简单的。

    元编程的优点(不是ABSE独有的):

    • 更改模型并重新生成一个完整的系统(想象重构特性而不是源代码行)。
    • 更改模型中的一些定义可以产生不同的程序(软件产品族)。
    • 很多人,真的

    元编程、代码生成、程序转换是软件开发中令人兴奋的新领域。然而,元编程需要一种新的技能:元思维。

        6
  •  2
  •   Klaim    16 年前

    基于元编程的库/代码有助于直接编写显式和简单的代码,这些代码将根据所使用的参数为您生成实现细节代码。

    Boost 充满了(C++)库,它们演示了元编程可以实现什么。一些好的(也许很难理解)例子是 Proto DSL , Spirit 允许使用 EBNF 直接在代码中使用语法,以及许多其他令人眩晕的库。

        7
  •  2
  •   Jeffrey Schaffner    8 年前

    我已经创建了一个程序工具,它将从任何MS Access数据输入表单生成ASP.NET网页源代码。我使用的技术是为每种类型的表单控件创建自己的ASP.NET文本模板。我只是从MS Access form objects元数据中插入诸如TOP、LEFT、HEIGHT、WIDTH、CONTROLSOURCE等值。

     <asp:TextBox ID="**ID**" runat="server" style="z-index: 1; left: **LL**px; top: **TOP**px; position: absolute"  Text='<%# Bind("[**CTLSOURCE**]") %>' />
    

    在获取textbox控件元数据值之后,我的程序生成文本框的代码

    <asp:TextBox ID="txtCustomerID" runat="server" style="z-index: 1; left: 50px; top: 240px; position: absolute"  Text='<%# Bind("[CustomerID]") %>' />
    

    我的程序在2-3秒内为一个MS-Access表单生成整个网页的源代码;可能需要数小时甚至数天的任务。

        8
  •  1
  •   JulesLt    16 年前

    您可以为所有内容编写或生成子类,添加包装器方法以添加访问控制并调用超类。使用元编程,您可以在运行时执行此操作,并且您的更改将自动应用于任何其他/更改的第三方类。

    在JSON示例中,通过使用类的内省,您应该能够生成序列化对象的代码,然后将其作为方法添加到类中。另一个极端是在编译之前生成或编写代码,每次类发生变化时都会产生影响,或者是一种完全通用的方法,每次需要映射时都对每个对象使用内省。

    根据所讨论的语言和运行时,元编程方法可能比完全通用/内省的方法快,但比前面的代码慢,因为您已经减少了对代码的大量数据查找。

        9
  •  1
  •   SK-logic    16 年前

    启动您的visualstudio(Eclipse、Netbeans等)。创建新项目。惊喜-您刚刚使用了一些元编程,通过从模板创建一个项目。这不实用吗?

        10
  •  0
  •   David Thornley    16 年前

    你可以看看普通LISP的宏或C++的模板,看看它们是如何使用的。这两个都是元编程在您使用的意义上。您会发现这两种方法在很多代码中都被大量使用。

    Lisp宏通常用于重新定义语言。例如,保罗·格雷厄姆的最后一章 On Lisp 为commonlisp创建一个面向对象的扩展。另一个例子是现在已经失效的 Garnet .

    用于C++的旧标准模板库(主要结合在标准库中)是一种引入大量容器和算法的方法,它们像在语言中构建一样,至少在集成和效率方面(不是句法上)。

        11
  •  0
  •   Colm Bhandal    7 年前

    在VBA中,我们经常使用元编程来创建属性。我们有各种各样的Excel电子表格,上面有许多标题,我们想为每个标题定义getter/setter属性,允许我们操作该标题下的单元格。手动操作将是一场噩梦。

    我们选择的元编程框架是Notepad++及其查找/替换正则表达式功能。以下是我们如何对属性进行元编程:

    • 将标题列表从Excel复制到记事本++
    • 录制Notepad++宏以清除数据(删除空格和特殊字符)。在本文的末尾,我们有一个以换行符分隔的字符串列表。
    • 手动将列表复制到另一个.CSV文件,并使用Excel生成行号列表。然后复制回Notepad++。

    最后,我们有一个混合了手动步骤、录制的宏和正则表达式的过程,我们可以在每次需要表的属性时重新应用它。我们做到了!非常有效。

    这就是元编程的力量。何时使用它取决于经验/直觉。但我建议回答这个问题:

    直接编写代码对我来说会更快吗?或者我能自动化部分/全部过程,并加快我的过程吗?

    这就给了你一条线,元编程不再有用。如果你能更快地编写代码,即使重复10次,也要做到!只有当它是成百上千次的重复,或者是你希望在将来多次重用的东西时,才可以对它进行元编程。