元编程有什么用?

Way*_*ner 69 language-agnostic code-generation metaprogramming

我读了:

我在元编程/代码生成背后的目的上承认了一些困惑.

有没有人有一个具体的例子,他们使用元编程/代码生成?更好的是伴随解释为什么它比替代品更好.

编辑:是否会被视为元编程?

Ben*_*oît 112

想象一个制造汽车的人.说它和使用电脑一样.
在某些时候,他意识到他总是或多或少地做同样的事情.
所以他建造工厂来制造汽车,而且它要好得多.他现在正在编程!
然而,再一次,在某种程度上,他意识到他在某种程度上总是在做同样的事情.
现在他决定建立工厂,建造汽车制造厂.这是元编程.

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

  • 这是一个很好的答案,但它显示了我觉得最令人讨厌的元编程.什么时候结束?什么阻止我们建立工厂,建造工厂,建造工厂,建造工厂,建造工厂的汽车? (5认同)
  • @XQLRSZ知道何时停止编写任何代码的方式相同:停止编写代码会使您的生活更轻松。除非您一遍又一遍地做某事,否则没有理由将其提取为一段代码。 (2认同)
  • 在某些环境中,它*永远*不会结束。请参阅 Nada Amin 的演讲,“软件应该自食其力”。https://www.youtube.com/watch?v=SrKj4hYic5A (2认同)

Ira*_*ter 20

我认为metaprogamming是"编写(或修改)其他程序的程序".(另一个答案说"制造工厂的工厂",很好的比喻).

人们可以找到各种用途:定制应用程序,生成样板代码,针对特殊情况优化程序,实现DSL,插入代码来处理正交设计问题("方面")......

值得注意的是,为了零碎地发明了多少不同的机制:文本模板,宏,预处理器条件,泛型,C++ - 模板,方面,反射......而且通常这些机制中的一些内置于某些语言中,并且其他语言的其他机制,大多数语言根本没有元编程支持.这种分散功能的分布意味着您可能能够在一种语言中进行某种类型的元编程,但有一些限制,但却无法在另一种语言中执行这些类型的元编程.这加剧了: - }

我一直关注的一个观察是,人们可以构建通用元编程机制,它可以以程序转换的形式使用任何语言 .一个程序转化为一个参数化的模式:"如果你看到句法,通过更换句法".

一个转换本身通常并不令人印象深刻,但数十个或数百个可以对代码进行重大改变.因为(复杂的)程序转换实际上可以模拟图灵机,所以它们可以执行任意代码更改,包括您发现散点图的所有那些逐点技术.

一种接受语言定义的工具.语言特定的转换并生成另一个应用这些转换的元数据编程工具:编写"编写程序的程序"的程序.

值是您可以应用此类工具对任意代码执行各种更改.并且,您不需要语言设计委员会意识到您需要特定类型的元编程支持,并且快点提供它以便您今天可以继续工作.

一个有趣的教训是,这样的机器需要强大的程序分析(符号表,控制和数据流分析等)支持,以帮助它专注于代码中的问题所在,以便元编程机制可以在那一点做一些事情(非常弱点的一个例子是方面的切入点规范,即"在看起来像这样的地方做出改变").

OP询问了应用元编程的具体示例.我们使用了我们的"元" - 目标编程工具(DMS Software Reengineering Toolkit)来自动在大型代码库上执行以下活动:

  • 语言迁移
  • 实施测试覆盖率和分析器
  • 实现克隆检测
  • 大规模的建筑再造
  • 工厂控制的代码生成
  • 嵌入式网络控制器的SOA化
  • 大型机软件的体系结构提取
  • 从阵列计算生成矢量SIMD指令
  • 将代码反向工程回到概念

跨多种语言,包括Java,C#,C++,PHP,......

OP也问道:"为什么这比替代方案好?" 答案与规模,时间和准确性有关.

对于大型应用程序,代码库的庞大规模意味着您没有资源或时间手动进行此类分析或更改.

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

从本质上讲,这些工具是人类根本无法做到的.

值得注意的是,这些工具没有创造力; 你仍然需要人来决定他们做什么,例如,决定任务是什么(参见上面的例子列表),并确定如何定义分析/转换以达到效果.你仍然需要程序员.然而,当一个元程序员用正确的知识武装这样一个工具时,生成的代码似乎是由一个非常快速,有创意的专家编码器构建的.


Geo*_*che 5

我已经最大程度地利用元编程来在不同的API之间进行桥接.

一个工作示例是FireBreaths 1,它可以简化编写暴露给JavaScript的C++类.通过提供一种用于将要被曝光的功能的登记设施,参数类型可以被检查,并从该嵌合代码在编译时从脚本API-类型转换为本地C++类型和背面,甚至直接支持产生,等JSAPIAutomapvector

举个简单的例子,考虑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 :(");
    }
}
Run Code Online (Sandbox Code Playgroud)

埋在那里的实际逻辑只有一行,检查和转换是烦人的和多余的.使用前面提到的注册工具(例如在构造函数中):

registerMethod("add", make_method(this, &MyClass::add));
Run Code Online (Sandbox Code Playgroud)

现在可以简单地写成:

long add(long a, long b) {
    return a+b;
}
Run Code Online (Sandbox Code Playgroud)

...并且框架负责为您生成必要的代码.

1:虽然我会实施一点......更清洁...如果我不得不重新开始