当然有一些语言可以在语言语法层面上实现自修改行为。Lisp程序可以包含宏,其中包括动态创建新控制结构的能力,以至于依赖广泛宏编程的两个Lisp程序看起来几乎像是用两种不同的语言编写的。类似的,Forth提供了约十二个基本操作的核心集合,需要使用该领域的语言(通常是某种必须精确且可编程的现实交互,例如工业机器人)构建程序。Forth程序员创建一个理解特定问题领域的语言的解释器,然后在该语言中编写更高级别的程序。
通常,这里的共同观点是将代码和数据视为等同的语言或系统,并且给用户修改它们的同等权利。例如,每个Lisp程序都是一个Lisp数据结构。这与Java等语言形成对比,在Java中,对程序代码和操作的数据进行了尖锐区分。
相关主题是自修改低级代码,这是汇编程序员在具有复杂指令集的小型计算机时代的一种相当常见的技术,它在早期的8位和16位微型计算机世界中也有所涉及。在这种编程惯用语中,为了提高速度或节省内存,程序将以“意识到”编译或解释指令存储在内存中的位置的方式编写,并可以逐字节地就地更改实际的机器级指令以影响其行为。
Forth是我能想到的最明显的东西。它是串联和基于堆栈的,其基本单元是一个单词。因此,您编写一系列单词,它们按照编写顺序执行,并且堆栈被明确操纵以影响参数传递、结果等。因此,一个简单的Forth程序可能如下所示:
6 3 + .
这句话包含了数字6、3、加号和点号。两个数字将它们的值推入堆栈,加号符号将从堆栈中弹出最后两个项并将它们相加,然后将结果推入堆栈。句点输出堆栈顶部的任何内容。
Forth 的一个基本特点是你可以定义自己的单词。由于所有单词都是运行时的一等成员,实际上你构建了一个应用程序特定的语法。定义了相关的单词之后,你可能会得到像下面的代码:
red circle draw
那将画一个红色的圆。
Forth在遇到每个单词序列时进行解释。然而,它区分编译时和普通单词。编译时单词执行的操作包括将一系列单词编译并存储为新单词。因此,这相当于在经典过程式语言中定义子程序。它们也是实现控制结构的手段。但是,您也可以定义自己的编译时单词。
因此,Forth程序通常定义其整个语法,包括相关的控制单词。
您可以在这里阅读基本介绍。
使用部分求值技术可以编译掉使用MIs实现这些东西所产生的开销。