【问题标题】:Is it possible to write code to write code?写代码可以写代码吗?
【发布时间】:2008-10-30 16:42:24
【问题描述】:

我听说有些事情作为计算机程序员是不能做的,但我不知道它们是什么。我最近想到的一件事是:有一个类可以复制它运行的程序的源代码,修改该程序并向它所在的类添加一个方法,然后运行,这不是很好吗?程序的副本并自行终止。代码可以写代码吗?

【问题讨论】:

    标签: theory


    【解决方案1】:

    如果您想了解可计算性的限制,请阅读halting problem

    在可计算性理论中,停止 问题是一个决策问题 可以表述如下:给定一个 程序和有限的描述 输入,决定程序是否 完成运行或将永远运行, 给定输入。

    艾伦·图灵在 1936 年证明了 解决所有人的停机问题的通用算法 可能的程序输入对不存在

    【讨论】:

    • 还好,如果问题受到约束,是可以解决的。
    【解决方案2】:

    首先查看quines,然后查看Macro-Assemblers,然后查看lex & yaccflex & bison。然后考虑self-modifying code

    这是一个quine(格式化,使用输出作为新输入):

    #include<stdio.h>
    
    main()
    {
      char *a = "main(){char *a = %c%s%c; int b = '%c'; printf(a,b,a,b,b);}";
      int b = '"';
      printf(a,b,a,b,b);
    }
    

    现在,如果您只是在寻找程序员无法做到的事情,请寻找 np-complete 的反面。

    【讨论】:

    • char *p="char *p=%c%s%c;main(){printf(p,34,p,34);}";main(){printf(p, 34,p,34);}
    • 嘿哇!您是否使变量中包含代码?我们能做到吗?
    • 请解释“寻找相反的 f np-complete。”你的意思是反过来吗?
    • main() 应该返回一个 int,但我确信这个例子只是为了展示风味......
    【解决方案3】:

    确实如此。很多病毒就是这样工作的!

    【讨论】:

    • 大多数病毒实际上并不编写代码,它们只是将自身或自身的一部分复制到现有代码中。
    【解决方案4】:

    了解一下:computability theory

    【讨论】:

      【解决方案5】:

      是的,大多数 Lisp 宏都是这样做的(仅举一个例子)。

      【讨论】:

        【解决方案6】:

        是的,当然是,但可能不在您所指的上下文中,请在 t4 上查看 post

        【讨论】:

          【解决方案7】:

          如果您看到函数式编程有很多机会编写代码来生成更多代码,那么像 Lisp 这样的语言不区分代码和数据的方式是其强大功能的重要组成部分。

          Rails 在创建新应用程序时从数据库模式生成各种默认模型和控制器类。用动态语言做这种事情是很标准的——我有一些 PHP 可以生成 php 文件,只是因为它是我当时正在处理的问题的最简单的解决方案。

          所以这是可能的。至于你问的问题——这可能有点模糊——你使用的是什么环境和语言?您希望代码做什么以及为什么需要添加它?一个具体的例子可能会带来更直接相关的反应。

          【讨论】:

            【解决方案8】:

            是的,可以创建代码生成器。 大多数时候,他们接受用户输入并生成有效代码。但还有其他可能性。

            也可以自行修改程序。但它们在 dos 时代更为常见。

            【讨论】:

              【解决方案9】:

              当然可以!事实上,如果你使用动态语言,类可以在程序仍在运行时改变自己(或另一个类)。它甚至可以创建以前不存在的新类。这称为元编程,它可以让您的代码变得非常灵活。

              【讨论】:

                【解决方案10】:

                您混淆/混淆了“写”一词的两种含义。一个含义是将字节物理写入介质,另一个含义是设计软件。当然,您可以让程序执行前者,如果它被设计为这样做的话。

                程序做程序员没有明确打算做的事情的唯一方法是表现得像一个生物:变异(在自身中融入一些环境),并以不同的速率复制不同的变异体(以避免完全灭绝,如果突变是终末的)。

                【讨论】:

                • 我的意思是第一个意思,但我很高兴你的有趣回答!我最近回到了这个问题,但是当我最初问这个问题时,我实际上是在询问是否有一个程序副本本身,更改副本,然后运行副本(然后可能会终止)。最近对write的第二个含义比较感兴趣!
                【解决方案11】:

                确实如此。我为 Paint.NET* 编写了一个效果,它为您提供了一个编辑器并允许您“即时”编写图形效果。当您暂停输入时,它会将其编译为 dll,加载并执行它。现在,在编辑器中,您只需要编写实际的渲染函数,创建 dll 所需的一切都由编辑器编写并发送到 C# 编译器。

                您可以在这里免费下载:http://www.boltbait.com/pdn/codelab/

                事实上,甚至还有一个选项可以在发送给编译器之前查看为您编写的所有代码。帮助文件(上面链接)谈到了它。

                也可以从该页面下载源代码。

                *Paint.NET 是一个免费的图像编辑器,您可以在这里下载:http://getpaint.net

                【讨论】:

                • nice :) 我一直想编写一个 paint.net 或 gimp 效果,但没有时间研究它
                【解决方案12】:

                关于人工智能,请看Evolutionary algorithms

                【讨论】:

                  【解决方案13】:

                  复制它运行的程序的源代码,修改该程序并向它所在的类添加一个方法,然后运行该程序的副本并自行终止

                  您还可以生成代码,将其构建为库而不是可执行文件,然后动态加载库,甚至无需退出当前正在运行的程序。

                  【讨论】:

                  • 哇!这正是我希望我们能做到的!
                  • 这并不一定意味着这是一个好主意,虽然:-)
                  【解决方案14】:

                  动态语言通常不像您建议的那样工作,因为它们没有完全独立的编译步骤。程序不需要修改自己的源代码、重新编译和从头开始。通常,新功能是动态编译和链接的。

                  Common Lisp 是一种很好的练习语言,但还有其他语言可以让您创建代码并在其中运行它。通常,这将通过一个名为“eval”或类似的函数来实现。 Perl 有一个“eval”函数,脚本语言通常都有这个能力。

                  有很多程序可以编写其他程序,例如 yacc 或 bison,但它们并没有您所寻找的动态质量。

                  【讨论】:

                    【解决方案15】:

                    看看Langtom's loop。这是最简单的自我复制“程序”的例子。

                    【讨论】:

                      【解决方案16】:

                      有一整类这样的东西叫做“代码生成器”。 (虽然,编译器也符合您设置的描述)。这些描述了这些野兽的两个领域。

                      大多数代码生成,采用某种形式的用户输入(大多数采用数据库模式)和随后编译的产品源代码。

                      更高级的可以输出可执行代码。对于 .NET,有一个专门用于创建可执行代码的完整命名空间 (System.CodeDom)。这些对象,您可以获取 C#(或其他语言)代码,对其进行编译,并将其链接到您当前正在运行的程序中。

                      【讨论】:

                        【解决方案17】:

                        我在 PHP 中执行此操作。

                        为了保留类的设置,我保留了一个名为 $data 的局部变量。 $data 只是一个字典/哈希表/关联数组(取决于你来自哪里)。

                        当您加载该类时,它包含一个基本定义数据的 php 文件。当我保存类时,它会为每个数据值写出 PHP。这是一个缓慢的写入过程(并且目前存在一些并发问题),但它比光读取要快。比使用数据库快得多(也更轻量)。

                        这样的东西不适用于所有语言。它在 PHP 中适用于我,因为 PHP 非常灵活。

                        【讨论】:

                          【解决方案18】:

                          编写代码生成器一直是可能的。借助 XML 技术,代码生成器的使用可以成为必不可少的工具。假设您为一家必须处理来自其他公司的 XML 文件的公司工作。编写一个使用 XML 解析器解析新 XML 文件的程序并编写另一个程序,该程序设置了所有回调函数来读取该格式的 XML 文件,这是相对简单的。您仍然需要编辑新程序以使其特定于您的需要,但是使用这种类型的代码生成器可以大大减少新 XML 文件(新结构、新名称)的开发时间。在我看来,这是 XML 技术优势的一部分。

                          【讨论】:

                            【解决方案19】:

                            lisp lisp lisp lisp :p

                            开玩笑,如果你想让生成代码的代码运行并且你有时间放松学习它并用递归的东西生成更多代码来打破你的想法,试着学习 lisp :)

                            (eval '(or true false))
                            

                            【讨论】:

                              【解决方案20】:

                              如果有一个类可以复制它运行的程序的源代码,修改该程序并向它所在的类添加一个方法,然后运行该程序的副本并运行,这不是很好吗?自行终止

                              几乎没有任何情况可以解决无法使用非自修改代码“更好”解决的问题。

                              也就是说,有一些非常常见(有用)的代码编写其他代码的案例。最明显的是任何服务器端 Web 应用程序,它生成 HTML/Javascript(嗯,HTML 是标记,但在理论)。此外,任何改变终端环境的脚本通常都会输出一个由父 shell 评估的 shell 脚本。 wxGlade 生成代码以创建基于 wx 的 GUI。

                              【讨论】:

                                【解决方案21】:

                                请参阅我们的DMS Software Reengineering Toolkit。这是读取和修改程序或通过组装片段生成程序的通用机器。

                                【讨论】:

                                  【解决方案22】:

                                  这是人工智能的基本问题之一。我个人希望这是不可能的——否则我很快就会失业!!! :)

                                  【讨论】:

                                    【解决方案23】:

                                    它被称为meta-programming,它既是编写有用程序的好方法,也是一个有趣的研究课题。 Jacques Pitrat 的Artificial Beings: the conscience of a conscious machine 书应该会让您很感兴趣。它主要与基于元知识的计算机程序有关。

                                    另一个相关术语是multi-staged programming(因为程序有几个阶段,每个阶段都会产生下一个)。

                                    【讨论】:

                                      猜你喜欢
                                      • 1970-01-01
                                      • 2013-08-27
                                      • 2011-06-23
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 2012-10-26
                                      • 2021-01-02
                                      • 2015-11-03
                                      相关资源
                                      最近更新 更多