6 types type-systems programming-languages static-typing dynamic-typing
我今天了解到动态类型编程语言在运行时进行类型检查,而不是在编译时进行类型检查。(如果我错了,请纠正我)。我想知道的是,动态类型语言在运行时如何找出类型以及它是如何工作的?动态类型语言也称为值类型语言,在动态类型语言的情况下,类型与值相关是什么意思?
由于我是初学者,我的问题对你们中的一些人来说不是一个好问题,请尝试从我的角度思考,我刚刚开始,我在任何地方都找不到这个答案。
更新
来自维基百科页面类型系统
动态类型检查语言的实现通常将每个运行时对象与包含其类型信息的“类型标记”(即对类型的引用)相关联。此运行时类型信息 (RTTI) 还可用于实现动态调度、后期绑定、向下转换、反射和类似功能。
现在什么是类型标签以及它是如何工作的,我的意思是如果你能告诉我它在内存中是如何表示的?
这取决于实施。以下是实现如何决定表示值的三个粗略示例。
术语注意事项:我将使用“值”一词来谈论作为参数传递给函数、放入字段等的位。在许多情况下,值可能是或包含指向额外内存的指针别处。
在这个实现中,一个值只是一个指向内存中对象的指针,每个对象在相同的偏移处都有一个“类型标签”,说明它是什么类型的东西。它可以是一个简单的枚举或指向某种“元类”的指针。
例如,一个整数将由一个指向具有两个字段的对象的指针表示:第一个包含类型标记INTEGER,第二个包含整数值。当谈论像整数这样的简单原始数据时,这被称为“装箱”表示。
优点是简单。装箱整数的缺点是每个算术运算 1) 都经过额外的指针间接寻址,2) 需要为结果分配一个对象。这通常真的很慢。
Java 虚拟机将这种表示用于所有类类型的变量和字段。这就是为什么int快而Integer慢(除非优化等)。
另一种可能的表示是使用两个词来表示每个值。第一个是类型标记,第二个是立即值(对于整数、布尔值、字符等类型)或指针(对于字符串、对象、数组等)。
这消除了与装箱整数等相关的分配和内存间接问题,但它使值表示增加了一倍,这是浪费。
第三种表示通过将类型标记和值压缩为单个单词来“优化”第二种表示。如果所有对象都分配为 32 位对齐,则每个有效指针都以 2 个零位结束。(或 3 表示 64 位对齐等)这些位可用于区分极少数基本类型。例如,这是一个标记系统:
xxxxxx00表示整数值xxxxxx(符号扩展)。这种表示中的整数称为“fixnums”。vvvvvv01表示vvvvvv解释为另一种小值(如布尔值、“空”、字符等)pppppp10表示地址pppppp00处的对象(该对象以更详细的类型标头开始)与上面的表示 2 一样,这种表示方案也避免了装箱(大多数)小数据,但它避免了膨胀,因为值仍然由单个单词表示。它需要与垃圾收集器进行一定程度的合作(识别和跟踪指针),但 2 也是如此。
对于像 Scheme 这样的语言,它具有无限大小的整数以及其他类型的数字,例如“flonums”(浮点数)和“ratnums”(精确有理数或分数),像这样a+b编译算术运算:
if a and b are both fixnums:
add a and b directly
on overflow, jump to the general addition function
otherwise, that's the result
otherwise, jump to the general addition function
Run Code Online (Sandbox Code Playgroud)
一般的加法函数只是缓慢地处理所有情况,在必要时计算出提升,并对给定的数字类型进行适当的工作。但是,如果大部分的时间a和b有fixnums,然后计算发生在线路和速度非常快。
这种表示既快速又紧凑,尽管操作(原始算术、对象字段获取等)在检查和补偿标记位方面变得更加复杂。这种方法的一个缺点是,如果您使用典型的类型化、安全的语言(如 Java、C#、ML 等)编写解释器/VM,则通常无法使用它。类型系统不会让您将整数部分转换为指针。你可以用 C 来做,这是不安全的。
这种表示思想的另一个变体是“NaN 编码”:大约有 2^51 位模式表示“不是数字”作为 IEEE 双精度浮点数。为什么不将有效的浮点数表示为它们本身并将其他值打包到 NaN 空间中?
以下是一些参考:
动态语言中的变量通常是对类实例或对象的引用(有时对于int某些语言来说是内置在数据类型中)。
它们可以在其“生命周期”(存在垃圾收集的情况下)接收对不同对象(或类实例)的引用,因此它们的类型是由对象的类型派生的(是对象的类型,int还是string用户定义的Person?)。
当确定对象的类型时,不同的语言会以不同的方式实现。
例如,Python 使用元类来确定类的类型,并在确定对象的类型时使用该信息。
Javascript 使用的对象除了普通属性说明符(类似于元类)之外,还包含普通数据类型(integer、float、character...)。