Smalltalk
Smalltalk是一种动态类型、反射式的面向对象编程语言。Smalltalk由艾伦·凯、Dan Ingalls、Ted Kaehler、Adele Goldberg等于1970年代初在施乐帕羅奧多研究中心开始开发。
Smalltalk对其它众多的程序设计语言的产生起到了极大的推动作用，特別是具有元类的Objective-C、CLOS、Python和Ruby等。1990年代涌现的许多软件开发思想得利于Smalltalk，例如设计模式、敏捷编程和代码重构等。
Smalltalk和许多程序设计语言不同，它不仅仅是一门语言。下面从几个不同的角度来解释Smalltalk。 最早的Smalltalk原型由艾伦·凯于1970年代初提出。类（来自Simula 67）、（来自LOGO）以及图形用户界面（来自Sketchpad）等概念的有机组合，构成了Smalltalk的最初的蓝图。
在1971年到1975年之间，艾伦·凯在Xerox PARC的小组，设计并实现了第一个真正的Smalltalk语言系统，編譯器由Dan Ingalls負責主要實作。这个系统被称为Smalltalk-71與Smalltalk-72，具有以下几个技术创新： 开发环境的革新相当迅速。虽然当时的位图显示器十分昂贵，但是艾伦·凯却说服了PARC，让他使用这些位图显示器，这使得艾伦·凯和他的小组，能够实现不同大小和字体的文字，使用多窗口环境，以及一些对图像处理的高端支持。Smalltalk-72影响了演员模型的发展，它的语法和执行模型，与现代的Smalltalk变体有着显著的差异。
在1975到1976年间，艾伦·凯小组认识到应当对执行效率和规模进行优化。于是他们在许多重要方面重新设计了Smalltalk系统，被称为Smalltalk-76，它在语言上：
前述的所有Smalltalk系统，都是在特殊的硬件上实现的，直到1977年至1978年，Bruce Horn和Ted Kaehler把Smalltalk-76移植到上，它是由Intel 8086处理器和自定显示器所组成的硬件环境。虽然这种硬件环境只生产了10台，但是它证明了在通常的处理器上实现Smalltalk的可能性。
在1979至1980年，部分受NoteTaker项目的影响，Smalltalk小组的注意力转移到Smalltalk的销售可行性上。小组设计并实现了新一代的Smalltalk系统，这次修改的目标着重于在标准硬件上的移植性等方面，被称为Smalltalk-80，它包括：
Smalltalk-80是在PARC之外能获得到的第一个语言变体，最初作为Smalltalk-80版本1，给与了少数公司（惠普、苹果公司、泰克和DEC）和大学（UC Berkeley），用于同行评审和在它们自己的平台上实现。后来在1983年普遍可获得的实现，叫做Smalltalk-80版本2，发行为虚拟机规定和映像（具有对象定义的独立于平台的文件）。
1988年Xerox PARC为了将Smalltalk推向市场而成立了分拆公司ParcPlace Systems。ANSI Smalltalk自从1998年来是标准的语言参考。
两个当前流行的Smalltalk实现变体，是这些最初Smalltalk-80映像的后代。Squeak是开源实现经由Apple Smalltalk，派生自Smalltalk-80版本1。经由Smalltalk-80 2.5和ObjectWorks（二者都是ParcPlace Systems的产品），派生自Smalltalk-80版本2。
如同其他面向对象语言，Smalltalk-80（而非Smalltalk-72）的中心概念是“对象” 。一个对象总是一个“类”的一个“”。类是描述它们的实例的属性和行为的“蓝图”。例如，一个GUI窗口类可以声明窗口有属性比如标签、位置和窗口是否可见。类还可以声明实例们支持操作比如打开、关闭、移动和隐藏。每个特定窗口对象对这些属性都有自己的值，它们每个都能进行它的类定义的操作。
Smalltalk对象确切的可以做三件事：
一个对象持有的状态总是私有于这个对象。其他对象只能通过发动请求（消息）至这个对象，来让它做出查询或变更这个状态。任何消息可以发送给任何对象：当接收到一个消息的时候，接收者确定这个消息是否合适。Alan Kay评论说，尽管关注于对象，消息才是Smalltalk中最重要的概念：“最大的想法是消息传递，它是Smalltalk/Squeak核心的全部意义所在（它是我们在Xerox PARC阶段从未真正完成的某种东西）。”
不同于多数其他语言，Smalltalk对象可以在系统运行的同时进行修改。现场编码和飞速应用补丁，是Smalltalk的主导编程方法论，并且是它高效的主要原因。
Smalltalk是“纯”面向对象编程语言，这意味着，不像C++和Java，在作为对象的值和作为基本类型的值之间没有区别。在Smalltalk中，基本值比如整数、布尔值和字符，在它们也是相应类的实例，和发送消息来调用它们上的运算的意义上，也是对象。编程者可以改变或扩展（通过子类）实现基本值的类，使得新行为可以定义到它们的实例，例如要实现一个的控制结构，甚至使得它们现存行为改变。这个事实被总结成常听到的一句短语：“在Smalltalk中，所有东西都是对象”，它可以更精确的表达为：“所有的值都是对象”，因为变量不是。
因为所有的值都是对象，类也是对象。每个类都是这个类的元类的一个实例。元类都是元类类codice_1的实例，它也是对象，并且是叫做codice_2的元类元类的实例。代码块是Smalltalk表达匿名函数的方法，也是对象。
Smalltalk-80语法是相当极简主义的，只基于了一小把的声明和保留字。事实上，Smalltalk中只保留了六个“关键字”：codice_3、codice_4、codice_5、codice_6、codice_7和codice_8。它们的准确术语是“伪变量”，是服从变量标识符规则的标识符，但指示了编程者所不能变更的绑定。codice_3、codice_4和codice_5伪变量是单例实例。codice_6和codice_7，在响应一个消息而激活的方法中，指称这个消息的接收者；但是发送给codice_7的消息，在这个方法的定义类的超类中查找方法，而非这个接收者的类中，这允许子类中的方法调用在超类中的同名方法。codice_8指称当前的活跃记录。
内建的语言构造只有消息发送、赋值、方法返回和某些对象的文字语法。从它最初作为给所有年龄儿童的语言开始，标准的Smalltalk语法以更像英语，而非主流编码语言的方式使用标点符号。语言余下部份，包括用于条件求值和迭代的控制结构，都由标准Smalltalk类库实现在内建构造之上。（出于性能上的原因，实现可以识别并特殊处理某些这种消息；但是，这只是优化而非硬性规定入语言语法的。）
谚语“Smalltalk语法适合一张明信片”，所提及的是的一个代码片段，展示了一个方法的所有基本标准语法元素：
exampleWithNumber: x 下列例子诠释了最常用的对象，可以在Smalltalk-80方法中被写为值。
数，下列是某些可能例子： 42 -42 123.45 1.2345e2 2r10010010 16rA000 最后两个项目分别是二进制和十六进制数。在codice_16前的数是底数或基数。基数不必须是二的幂；例如codice_17是一个有效的数值，等价于十进制的codice_18。
字符书写时带有前导的美元符：
$A
字符串是包围在单引号内的字符序列：
'Hello, world!'
要在一个字符串中包括一个引号，使用另一个引号来转义：
'I said, "Hello, world!" to them.'
双引号不需要转义，因为单引号界定字符串：
'I said, "Hello, world!" to them.'
两个相等的字符串（字符串相等，如果它们包含完全相同的字符）可以是驻留在内存不同位置中的不同对象。除了字符串，Smalltalk有叫做（codice_19）的字符序列对象的类。符号保证是唯一的，没有是不同对象的两个相等的符号。因此，符号非常易于比较并经常用于语言制品，比如消息选择子（见后）。
符号被写为codice_20跟随着。比如：如果一个序列不好括空白或标点字符，还可以写为：数组：定义了四个整数的一个数组。
很多实现支持下列字节数组（codice_21）的文字语法：定义了四个整数的字节数组。
最后却重要的是，块（匿名函数文字）:
[... 一些smalltalk代码 ...]
块在下文中进一步详细解释。
很多Smalltalk方言为其他对象实现了额外的语法，但是上述的是所有方言都本质上支持的。
在各种Smalltalk中共同使用的有两种变量：实例变量和临时变量。其他变量和有关术语依赖于特定实现，例如有类共享变量和名字空间共享变量，而Squeak和很多其他实现，有类变量、池变量和全局变量。
在Smalltalk中临时变量声明是在方法（见后）内声明的变量。它们声明在方法的顶部，作为由竖杠包围的空格分隔的名字。例如：
声明一个临时变量名叫codice_22，可以包含初始值codice_5。
多个变量可以在一组竖杠内声明：
声明了两个变量：codice_22和codice_25。所有变量都要初始化。字符串的索引变量，初始化为codice_26字符或初始为codice_27的codice_21，此外的所有变量初始化为codice_5。
按命名约定，实例变量、临时变量、方法或块的参数，应当以小写字母开头，指示它们具有私有作用域，它们合称为局部变量。而全局变量、类变量、池字典、类名字，应当以大写字母开头，它们合称为共享变量。
变量通过codice_30语法来指定一个值。比如：
vowels := 'aeiou'
指定字符串codice_31至前面声明的codice_25变量。这个字符串是个对象（在单引号之间的字符序列是文字字符串的语法），在编译时间由编译器创建。
在最初的Parc Place映像中，现在下划线（codice_33）的字形，在那时是左向箭头（codice_34）字形（就像1963年版本ASCII代码中那样）。Smalltalk最初接受左向箭头，作为唯一的赋值算符。一些现代代码仍然包含充当赋值的下划线，会让人想起这种最初的用法。多数现代的Smalltalk实现接受要么下划线，要么冒号等号语法。
消息是Smalltalk中最基础的语言构造。所有控制结构都实现为消息发送。Smalltalk缺省的采用动态分派和单一分派策略（相对于其他一些面向对象语言使用的多分派）。
下列例子是发送消息codice_35至数值codice_36：
42 factorial
在这种情况下，codice_36叫做这个消息的“接收者”，而codice_35是消息的选择子。接收者通过返回一个值来相应这个消息（这个情形中是codice_36的阶乘）。同其他事物一样，消息的结果可以赋值给一个变量：
aRatherBigNumber := 42 factorial
上面的codice_35是“一元”消息，因为只涉及了一个对象，即接收者。消息可以承载额外的对象作为实际参数，比如：
2 raisedTo: 4
在这个表达式中，涉及了两个变量：codice_41作为接收者而codice_42作为消息的实际参数。消息结果，或用Smalltalk的说法，回答被认定为codice_43。这种消息叫做“关键字”消息。消息可以有多个实际参数，使用如下语法:
'hello world' indexOf: $o startingAt: 6
它的回答是在接收者字符串中字符codice_44的索引，从索引codice_45开始查找。这个消息的选择子是codice_46，构成自两个部份或关键字。
这种关键字和实际参数的交织意图改进代码的可读性，因为实际参数由前导于它们的关键字来解释。例如，要建立一个矩形的表达式使用C++或Java类语法可以写为：
new Rectangle(100, 200);
不清楚这些实际参数分别是什么。与之相反，在Smalltalk中，这个代码可以写为：
Rectangle width: 100 height: 200
这个情况下接收者是codice_47类，回答是这个类的具有指定宽度和高度的一个实例。
最后，多数特殊（非字母）字符可以被用作所谓的“二元消息”。这些允许了数学和逻辑算符以传统形式书写：
3 + 4
它发送消息codice_48给接收者codice_49，具有codice_42作为实际参数传递（回答将是codice_51）。类似的：
3 > 4
将消息codice_52发送给codice_49具有实际参数codice_42（回答将是codice_4）。
注意，Smalltalk-80语言自身不包含着这些算符的含义。上述的结果都只是这些消息的接收者（这里是数值实例）为了响应消息codice_48和codice_52而定义并返回的。
这个机制的副作用是运算符重载。消息codice_52可以被其他对象所理解，允许使用形如codice_59的表达式来比较它们。
一个表达式可以包括多次消息发送。在这个情况下，表达式依据一个简单的优先级次序来分析。一元消息有最高的优先级，随后是二元消息，最后是关键字消息。例如：
3 factorial + 4 factorial between: 10 and: 100
被求值如下：最后的消息发送的回答是整个表达式的结果。
在需要的时候使用圆括号可以改变求值的次序。例如：
(3 factorial + 4) factorial between: 10 and: 100
将改变表达式含义，首先计算codice_75产生codice_72。接着codice_72接收第二个codice_35消息，产生codice_79。codice_79接着接收codice_71，回答codice_4。
注意因为二元消息的含义不是硬性规定入Smalltalk-80语法的，它们全部都被认为有相等的优先级并简单的从左至右来求值。因此，使用二元消息的Smalltalk表达式的含义可能不同于传统释义：
3 + 4 * 5
被求值为codice_83，产生codice_84。要得到预期回答codice_85，必须使用圆括号来显式的定义运算次序：
3 + (4 * 5)
一元消息可以一个接一个的写成：
3 factorial factorial log
它发送codice_35到codice_49，接着codice_35到这个结果（codice_45），接着codice_90到这个结果（codice_91），产生结果codice_92。
在下列（假想）例子中书写了一序列的表达式，每个都用点号分隔。这个例子首先建立类codice_93的一个新实例，存储它在一个变量中，接着发送两个消息给它。 window := Window new. window label: 'Hello'. window open 如果向上述例子这样一序列消息都发送给相同的接收者，它们也可以写为，具有用分号分隔的单独消息： Window new 这种将前面例子的重新为一个单一表达式，避免了对将新窗口存储在临时变量的需要。依据平常的优先级规则，一元消息codice_94首先发送，接着codice_95和codice_96被发送到codice_94的回答。
可以使用codice_98消息来返回一个级联消息的接收者。
代码块（匿名函数）可以被表达一个文字值（它是一个对象，因为所有值都是对象）。这是通过方括号达成的：
[ :params |  ]
这里的codice_99是代码可以接受的形式参数的列表。这意味着Smalltalk代码：
[:x | x + 1]
可以理解为：
或用λ演算表达为：
而如下：
[:x | x + 1] value: 3
可以被求值为：
或用λ演算表达为：
结果的块对象可以形成一个闭包：它可以在任何时间访问它外围的词法作用域内的变量。块是头等对象。
块可以通过发送给它们codice_100消息来执行。块有一个参数用codice_101，有2个参数使用codice_102，以此类推直到4个参数，对多于4个参数使用codice_103并将参数作为数组传递。
块返回（常称为回答）其主体的最后一个表达式的值，除非有一个由显式的codice_104指示的返回，这时返回这个返回表达式的值。
块的文字表示是一种创新，它一方面允许特定代码有更重大的可读性；它允许涉及迭代的算法一更清晰和简洁的方式编码。典型的在某些语言中使用循环写成的代码，可以在Smalltalk中使用块简洁的书写，有时在单一一行之内。更重要的方面是，块允许控制结构使用消息来表达并具有多态，因为块推延了计算并可以使用多态来选择替代者。所以在Smalltalk中codice_105被书写和实现为： expr ifTrue: [ expr为真时求值的语句 ] ifFalse: [ expr为假时求值的语句 ] 再比如选择：
positiveAmounts := allAmounts select: [:anAmount | anAmount isPositive] 注意这与函数式编程有关，这里的计算模式被抽象成了高阶函数。例如，在一个搜集上的消息codice_106，等价于在一个适当的函子上的高阶函数filter。
在Smalltalk中控制结构没有特殊的语法。它们转而实现为发送到对象上的消息。例如，条件执行被实现为，发送消息codice_107到一个布尔对象，传递一个代码块作为实际参数，它被执行当且仅当布尔接收者为真。有下列代码演示： result := a > b 块也被用来实现，用户定义控制结构、枚举器、访问器、异常处理、可插拔的行为和很多其他模式。例如： aString := 'This is a string'. vowels := aString select: [:aCharacter | aCharacter isVowel].
在最后一行，向字符串发送了消息codice_106，具有一个代码块文字作为实际参数。作为给codice_106消息的实际参数的代码块，表示一个测试，代码块文字将被用作一个谓词函数，它回答codice_3，当且仅当这个字符串的一个元素，应当被包括在满足这个测试的字符搜集之中。
字符串对象，通过迭代经过它的成员（即向自身发送消息codice_111），来响应codice_106消息，将选择块（codice_106的实际参数codice_114）嵌入在迭代块的代码之中，把它自身包含的每个字符，都作为实际参数传给迭代块，而各做一次求值。在求值迭代块的时候（被发送了消息codice_101），将迭代元素传给选择块（codice_114引用的块文字codice_117），它回答一个布尔值；接着向它发送消息codice_107，如果这个布尔值是对象codice_3, 这个字符被增加到要返回的字符串。
因为codice_106方法被定义在抽象类codice_121中，并且搜集类的类方法中，实例创建方法有codice_122、codice_123一直到codice_124方法，它可以如下这样使用：
rectangles := OrderedCollection aPoint := Point x: 20 y: 20. collisions := rectangles select: [:aRect | aRect containsPoint: aPoint].
异常处理机制codice_125类，及其子类比如codice_126，使用块作为处理器（类似于CLOS风格异常处理）：
[ 一些运算. Error signal: 'an error occurred' ] on: Error do:
异常处理器的codice_127实际参数提供到挂起运算的状态的访问（栈帧、行号、接收者和实际参数等），并且还被用来控制计算怎样继续（通过发送codice_128、codice_129、codice_130或codice_131之一）。
类通过实例变量定义它的实例的结构，通过方法定义它的实例的行为。每个方法都有叫做选择子的一个名字，它在这个类之内是唯一性的。下面是个平凡的类定义：
Object subclass: #MessagePublisher
多数这种定义经常由编程环境来填充。这里的类定义是给codice_132类的一个消息，用来建立它叫做codice_133的一个子类。
在Smalltalk中类是头等对象，它可以就像任何其他对象一样接收消息，并可以在执行时间动态的创建。codice_134方法，定义在codice_135类中。
在Smalltalk中，是这个实例私有的。在需要于这个类的所有实例和这个类本身之间，共享某个数据的时候，要使用。池变量是在可以没有继承关联的多个类之间共享的变量。池变量最初存储在池字典中，现在它们应当被定义为专门的类（codice_136的子类）的类变量。
codice_137指示有关的类的“群组”，在现代Smalltalk版本如Pharo中被替代为codice_138，包系统是利用简单的命名约定，组织Squeak和Pharo源代码的简单而轻量级的方式。
当一个对象接收到一个消息的时候，调用匹配这个消息名字的一个方法。所有方法都是公开的和虚拟的（也就是动态查找的）。方法被分组入指示它们意图的协议（protocol）之中。
为一个类增加方法涉及到codice_139类，其中的codice_140方法，编译一个方法源代码并返回一个codice_141类的实例；codice_142方法，将给定的一个编译过的方法增加到方法字典中。在codice_139类的子类codice_144类中，codice_145方法，编译一个方法的源代码，并为这个方法指派上给定的归类（对于方法称为协议）。
下列代码定义一个方法codice_146，并且这个定义将在这个对象收到codice_146消息的时候发生。
publish 下列方法演示了接收多个实际参数并返回一个值：
quadMultiply: i1 and: i2
这个方法的名字是codice_148。返回值通过codice_104算符来指定。
对象负责在运行时间动态的确定，执行哪个方法来响应一个消息，尽管在很多语言中，这可能是（有时或总是）在编译时间静态确定的。
执行任何前导了codice_104（脱字符或codice_151）的表达式，都导致这个方法于这一点退出，并返回这个表达式的值。终止而没有显式返回某个表达式的一个方法，将隐含的返回自身。
为一个类新建一个实例，要用到在codice_139类中定义的codice_94方法。下列例子代码：
MessagePublisher new
建立（并返回）codice_133类的一个新实例。这典型的赋值到一个变量：
publisher := MessagePublisher new
但是也有可能发送一个消息到一个临时的、匿名对象：
MessagePublisher new publish Hello world程序，实质上被所有计算机语言的课本用作要学习的第一个程序，它展示了这个语言的最基本语法和环境。对于Smalltalk，这个程序可极其简单的书写。下列代码中，消息codice_155被发送给对象codice_156，具有字符串文字codice_157作为它的实际参数。调用codice_155方法，导致它的实际参数（字符串文字codice_157），显示在副本（终端）窗口：
Transcript show: 'Hello, world!'.
注意需要打开Transcript窗口，来看到这个例子的结果。
反射是一个计算机科学术语，适用于有能力检查它们自己的结构的软件程序，例如检查它们的分析树或输入和输出参数的数据类型。反射是动态、交互式语言比如Smalltalk和Lisp的一个特征。具有反射的交互式程序（要么解释的要么编译的）维护所有内存内对象的状态，包括代码对象自身，这是在解析/编译期间生成的，并且是在编程上可访问和修改的。
反射也是Smalltalk这种有元模型的语言的一个特征。元模型是描述这个语言的模型，开发者可以使用元模型来做事，比如游历、检查和修改一个对象的分析树，或找到特定种类的结构的所有实例（例如在元模型中codice_160类的所有实例）。
Smalltalk-80是完全的反射式系统，用Smalltalk-80语言实现。Smalltalk-80提供了结构性和计算性反射二者。Smalltalk是结构性反射式系统，其结构是由Smalltalk-80对象定义的。定义这个系统的类和方法也是对象，并且完全是它们所有助力定义的系统的一部份。Smalltalk编译器将文本源代码编译成方法对象，典型是的codice_141的实例。通过把它们存储入一个类的方法字典，而增加到这个类。类层级的定义类的那部份，可以向系统增加新类。这个系统是通过运行建立或定义类和方法的Smalltalk-80代码来扩展的。Smalltalk-80系统是个现场（living）系统，承载着在运行时间扩展自身的能力。
因为类是对象，可以向它们提问比如：“你实现了哪些方法？”或“你定义了什么字段/槽/实例变量？”。所以通过能应用于系统中的任何对象的普通的代码，对象可以轻易的检查、复制、（去）序列化，诸如此类。
Smalltalk-80还提供计算性反射，有能力观察系统的计算状态。在派生自最初Smalltalk-80的语言中，一个方法的当前活动（activation），可以作为通过伪变量命名的一个对象来访问，这个伪变量是作为六个保留字之一的codice_8。通过发送消息至codice_8，一个方法活动可以提问比如：“谁给你发送了这个消息？”。这些设施使得有可能实现协程，或类似Prolog的回溯，而不需要修改虚拟机。异常系统也是使用这个设施实现的。这个设施更有趣的用法之一，是在 web框架之中，它通过为每个编辑的页面存储续体，并在它们之间切换来导航一个web站点，缓解了编程者处理Web浏览器的返回按钮的复杂性。使用Seaside编程web服务器，可以使用更常规的编程风格来完成。
Smalltalk如何使用反射的一个例子，是处理错误的机制。当一个对象被发送了一个它没有实现的消息的时候，虚拟机发送给这个对象codice_164消息，具有这个消息的实化作为实际参数。这个消息（它是另一个对象，是codice_165的实例），包含这个消息的选择子和它的实际参数的一个codice_166。在交互式Smalltalk系统中，codice_164的缺省实现，是打开一个错误窗口（一个codice_168）向用户报告错误。通过它和反射设施，用户可以检查错误在其中发生的上下文，重新定义犯错的代码，并继续，这一切都在这个系统之中，使用Smalltalk-80的反射设施。
通过建立只理解（实现）codice_164的一个类，可以建立一个实例，经由它的codice_164方法能拦截发送给它的任何消息。这种实例可以叫做透明代理。可以使用这种代理来实现很多设施，比如分布式Smalltalk，这里的消息在多个Smalltalk系统之间交换，和数据库接口，这里的对象透明的从数据库中排除错误，还有promise等。分布式Smalltalk的设计影响了如CORBA这样的系统。
多数流行的编程系统，将静态的程序代码（以类定义、函数或过程的形式），分离于动态的或运行时间的程序状态（比如对象或其他形式的程序数据）。它们在程序启动的时候装载程序代码，而任何先前的程序状态必须从配置文件或其他数据源显式的重新建立。程序（和编程者）未显式保存的设置，在每次重启时都必须再次设立。传统的程序在每次程序保存一个文件、退出和重载的时候，还失去很多有用的文档信息。这会失去细节比如回退历史或光标位置。基于映像的系统不会因为计算机关闭或OS更新，而强制失去所有这些东西。
但是很多Smalltalk系统，不区分程序数据（对象）和代码（类）。事实上，类也是对象。因此，多数Smalltalk系统，存储整个程序状态（包括类和非类对象二者）在一个文件之中。这个映像可以接着由Smalltalk虚拟机装载，将类Smalltalk系统恢复成先前的状态。这是受到了FLEX的启发，它是Alan Kay创建的语言并描述于他的科学硕士毕业论文中。
Smalltalk映像类似于（可重启的）核心转储，并可以提供与核心转储相同的功能，比如延迟或远程调试，具有对出错时刻的程序状态的完全访问。将应用代码建模为某种形式的数据的其他语言比如Lisp，也经常使用基于映像的持久存储。这种持久存储的方法，对于快速开发是强力的，因为所有开发信息（比如程序的解析树），都保存而利用于调试。但是它作为一个真实的持久存储机制，也有一个严重的缺点。首先，开发者可能经常想要隐藏实现细节，并使它们在运行时间不可获得。出于法律和维护的原因，允许任何人在运行时间修改程序，对于在运行时间环境不暴露源代码的编译后的系统，不可避免的介入复杂性和潜在的错误。其次，尽管持久存储机制易于使用，它缺乏多数多用户系统需要的真正持久存储能力。最明显的是进行同多个用户并行访问相同的数据库的事务。
OpenSmaltalk VM（OS VM）是Smalltalk运行时环境的著名实现，很多现代Smalltalk VM基于或派生自它。OS VM自身是从一组Smalltalk源代码文件（它们叫做VMMaker），转译成原生C语言源代码（通过使用叫做Slang的转译器），它依次再针对特定平台和硬件架构来编译，实际上确使Smalltalk映像的跨平台执行。源代码可以在GitHub上获得并在MIT许可证下发布。OS VM的知名派生者有：