根据 CLOS(Common Lisp),类型系统的目的是什么?
What is the purpose of the type system in light of CLOS (Common Lisp)?
据我了解,Common Lisp 对象的内存布局(按位标记由 CLOS (classes) 定义。
我理解每个class都有对应的类型,但不是每个类型都有对应的class,因为类型可以是复合的(列表)。我认为类型就像逻辑约束,而不是 class 带有标记方案的具体 "types"es。
如果这是正确的,类型系统除了作为逻辑约束(例如指定整数必须在特定范围内,或者数组包含特定类型)之外是否还有其他用途?
如果这不正确,那么根据 CLOS,类型系统的实际用途是什么?谢谢。
CLOS 是在游戏后期添加到 CL 中的(它不是为 CL 设计的唯一对象系统)
即使使用 CLOS,编译器也可以使用类型系统进行优化,用户可以使用其推理代码。
类型系统定义了不同的对象来做不同的事情。 CLOS 系统更多地用于为某些程序员以更合乎逻辑的方式定义类型的特殊行为的方法。来自 Java,CLOS 系统对我来说更符合逻辑和系统,因此它对一些程序员有一定的作用。我喜欢将 CLOS 系统视为 Java 中的 class,例如 Integer class,以及类似于 Java 中的原始类型的类型系统。 CLOS 系统只是帮助您以比创建结构恕我直言更系统的方式使用方法扩展对象。
一个对象一次只有一个class,而它可以满足多种类型。
类型系统是一个格子,您可以在其中计算两种类型的最小上限和最大下限(分别使用 or
、and
),并且它承认顶级类型 (T)和一个底层类型(NIL类型,与NULL类型不同)。
Common Lisp 的实现必须能够确定一个值是否属于一个类型,并且以原子类型说明符开头,如 character
或 integer
,并以复合类型说明符增长(可由用户定义)。
但是这是使用标签还是通过静态分析来完成,留给实现;实际上,CL 在某些情况下无法精确地静态确定对象的类型(T 除外),这仅仅是因为可以在以后重新定义对象:您不能假定其类型是固定的(例如:a函数;这就是内联或全局声明可能有助于类型推断的原因)。
但是如果你有一个类型可以保证不变的范围,编译器可以自由地使用未装箱的数据类型来存储值。那么你没有标记数据。变量类型的局部声明就是这种情况,对于专门的数组也是如此:一旦构建了一个数组,其元素类型就不会随时间改变,并且在某些情况下知道一个数组只包含 (integer 0 15)
个元素可以是用于更有效地打包数据。
一个类型是一组值。
类型说明符是一种简洁地表示类型的方法。
实现可能会做各种标记和注册,以帮助他们理清事物的类型,但这并不是类型概念所固有的。
A class 是描述一组其他对象的对象。由于为这样的集合(类型)取一个简洁的名称非常有用,Common Lisp 将 class 名称注册为相应对象集的类型说明符。这就是类型与 classes.
的全部关系
我认为远离事物的实现很重要,而是专注于语言如何看待它们。很明显,实现需要有足够的信息来知道给定对象是什么类型的东西,并且它将使用某种 'tag' 来做到这一点(这可能是也可能不是附加到对象的一些额外位——例如,其中一些可能是地址的前导位)。下面我将其称为 'representational type'。但是您实际上几乎无法从该语言访问该实现细节。人们很容易认为,type-of
告诉你一些将 1-1 映射到表示类型的东西,但事实并非如此:例如,(type-of (cons 1 2)
允许 return (cons integer integer)
,我认为可能允许 return (cons integer number)
或 (cons (integer 1 1) (integer 2 2))
。所有这些不太可能有不同的表示类型:确实存在 can't be since (type-of 1)
can return (integer m n)
for a infinite number m
& n
.
的值
下面介绍语言如何思考事物,以及 CL 中 classes 和类型之间的差异。
类型系统和 class 系统都由一个 有界网格 类型 / class 组成。作为一个 格子 意味着对于任何一对对象都有一个唯一的上界(因此,对于类型,一个唯一的类型,两种类型都是子类型,并且没有子类型是真)和下限(相反)。 有界表示有顶底型/class.
类
- 类 是第一个 class 对象(例如,您可以将 class 存储在变量中)。
- 所有对象(包括classes)都属于一个class,并且有一个明确定义的运算符可以找到任何对象所属的立即数class。
- 数量有限 class。
- 对象的 class 与其表示类型非常接近,但不完全对应(例如,可能有专门的数组类型没有对应的 classes)。
- 类 可以用作类型:
(type-of 1 (class-of 1))
和 (subtypep (class-of 1) '(integer 0 1))
一样(答案分别为 t
和 nil, t
)。
类型
类型是表示具有共同属性的对象集合的方法,但它们本身并不是对象:它们,如果有的话,只是事物集合的名称——语言规范称之为 'type specifiers'。特别是 有无数种类型 :例如,想想类型 (integer m n)
。这种无限类型中的一小部分对应于表示类型——告诉系统某物是什么东西的实际信息——但显然大多数不是。可能存在没有对应类型的代表性类型。
我认为类型在实践中有三个用途。
- 类型信息可以告诉系统使用什么表示类型,这可以帮助它检查事物是否是正确的表示类型并优化事物。
- 类型信息可以让系统进行推断,这对事情有很大帮助。
- 类型信息可以让程序员谈论他们正在处理什么样的事情,即使这些信息对系统没有帮助。系统可以将此类声明视为有关类型的断言,这可以使程序更安全且更易于调试。这是类型的一个重要原因:即使系统不检查它们,阅读您的代码的人知道它期望 [0, 30] 中的整数也很有用,即
(integer 0 30)
.事实上,即使系统不自动检查声明,您也可以强制检查,比如 (check-type x '(integer 0 30) ...)
.
第二个案例很有意思。假设我有一些东西,我已经告诉系统它的类型是 (double-float 0.0d0)
。就表示类型而言,这不太可能比 double-float
更有用。但是如果我取这个东西的平方根那么知道这个类型可能确实非常有用:系统可以知道结果是 double-float
,而不是 (complex double-float)
,而这些类型是极不可能的在代表性上是相同的。所以系统可以使用我的类型声明以这种方式进行推断(并且这些推断可以级联通过程序)。请注意,classes 不能这样做(至少 CL 的 classes 不能),对象的表示类型也不能:你需要更多信息。
所以是的,类型有许多非常有用的用途,classes 无法满足这些用途。
据我了解,Common Lisp 对象的内存布局(按位标记由 CLOS (classes) 定义。
我理解每个class都有对应的类型,但不是每个类型都有对应的class,因为类型可以是复合的(列表)。我认为类型就像逻辑约束,而不是 class 带有标记方案的具体 "types"es。
如果这是正确的,类型系统除了作为逻辑约束(例如指定整数必须在特定范围内,或者数组包含特定类型)之外是否还有其他用途?
如果这不正确,那么根据 CLOS,类型系统的实际用途是什么?谢谢。
CLOS 是在游戏后期添加到 CL 中的(它不是为 CL 设计的唯一对象系统)
即使使用 CLOS,编译器也可以使用类型系统进行优化,用户可以使用其推理代码。
类型系统定义了不同的对象来做不同的事情。 CLOS 系统更多地用于为某些程序员以更合乎逻辑的方式定义类型的特殊行为的方法。来自 Java,CLOS 系统对我来说更符合逻辑和系统,因此它对一些程序员有一定的作用。我喜欢将 CLOS 系统视为 Java 中的 class,例如 Integer class,以及类似于 Java 中的原始类型的类型系统。 CLOS 系统只是帮助您以比创建结构恕我直言更系统的方式使用方法扩展对象。
一个对象一次只有一个class,而它可以满足多种类型。
类型系统是一个格子,您可以在其中计算两种类型的最小上限和最大下限(分别使用 or
、and
),并且它承认顶级类型 (T)和一个底层类型(NIL类型,与NULL类型不同)。
Common Lisp 的实现必须能够确定一个值是否属于一个类型,并且以原子类型说明符开头,如 character
或 integer
,并以复合类型说明符增长(可由用户定义)。
但是这是使用标签还是通过静态分析来完成,留给实现;实际上,CL 在某些情况下无法精确地静态确定对象的类型(T 除外),这仅仅是因为可以在以后重新定义对象:您不能假定其类型是固定的(例如:a函数;这就是内联或全局声明可能有助于类型推断的原因)。
但是如果你有一个类型可以保证不变的范围,编译器可以自由地使用未装箱的数据类型来存储值。那么你没有标记数据。变量类型的局部声明就是这种情况,对于专门的数组也是如此:一旦构建了一个数组,其元素类型就不会随时间改变,并且在某些情况下知道一个数组只包含 (integer 0 15)
个元素可以是用于更有效地打包数据。
一个类型是一组值。
类型说明符是一种简洁地表示类型的方法。
实现可能会做各种标记和注册,以帮助他们理清事物的类型,但这并不是类型概念所固有的。
A class 是描述一组其他对象的对象。由于为这样的集合(类型)取一个简洁的名称非常有用,Common Lisp 将 class 名称注册为相应对象集的类型说明符。这就是类型与 classes.
的全部关系我认为远离事物的实现很重要,而是专注于语言如何看待它们。很明显,实现需要有足够的信息来知道给定对象是什么类型的东西,并且它将使用某种 'tag' 来做到这一点(这可能是也可能不是附加到对象的一些额外位——例如,其中一些可能是地址的前导位)。下面我将其称为 'representational type'。但是您实际上几乎无法从该语言访问该实现细节。人们很容易认为,type-of
告诉你一些将 1-1 映射到表示类型的东西,但事实并非如此:例如,(type-of (cons 1 2)
允许 return (cons integer integer)
,我认为可能允许 return (cons integer number)
或 (cons (integer 1 1) (integer 2 2))
。所有这些不太可能有不同的表示类型:确实存在 can't be since (type-of 1)
can return (integer m n)
for a infinite number m
& n
.
下面介绍语言如何思考事物,以及 CL 中 classes 和类型之间的差异。
类型系统和 class 系统都由一个 有界网格 类型 / class 组成。作为一个 格子 意味着对于任何一对对象都有一个唯一的上界(因此,对于类型,一个唯一的类型,两种类型都是子类型,并且没有子类型是真)和下限(相反)。 有界表示有顶底型/class.
类
- 类 是第一个 class 对象(例如,您可以将 class 存储在变量中)。
- 所有对象(包括classes)都属于一个class,并且有一个明确定义的运算符可以找到任何对象所属的立即数class。
- 数量有限 class。
- 对象的 class 与其表示类型非常接近,但不完全对应(例如,可能有专门的数组类型没有对应的 classes)。
- 类 可以用作类型:
(type-of 1 (class-of 1))
和(subtypep (class-of 1) '(integer 0 1))
一样(答案分别为t
和nil, t
)。
类型
类型是表示具有共同属性的对象集合的方法,但它们本身并不是对象:它们,如果有的话,只是事物集合的名称——语言规范称之为 'type specifiers'。特别是 有无数种类型 :例如,想想类型 (integer m n)
。这种无限类型中的一小部分对应于表示类型——告诉系统某物是什么东西的实际信息——但显然大多数不是。可能存在没有对应类型的代表性类型。
我认为类型在实践中有三个用途。
- 类型信息可以告诉系统使用什么表示类型,这可以帮助它检查事物是否是正确的表示类型并优化事物。
- 类型信息可以让系统进行推断,这对事情有很大帮助。
- 类型信息可以让程序员谈论他们正在处理什么样的事情,即使这些信息对系统没有帮助。系统可以将此类声明视为有关类型的断言,这可以使程序更安全且更易于调试。这是类型的一个重要原因:即使系统不检查它们,阅读您的代码的人知道它期望 [0, 30] 中的整数也很有用,即
(integer 0 30)
.事实上,即使系统不自动检查声明,您也可以强制检查,比如(check-type x '(integer 0 30) ...)
.
第二个案例很有意思。假设我有一些东西,我已经告诉系统它的类型是 (double-float 0.0d0)
。就表示类型而言,这不太可能比 double-float
更有用。但是如果我取这个东西的平方根那么知道这个类型可能确实非常有用:系统可以知道结果是 double-float
,而不是 (complex double-float)
,而这些类型是极不可能的在代表性上是相同的。所以系统可以使用我的类型声明以这种方式进行推断(并且这些推断可以级联通过程序)。请注意,classes 不能这样做(至少 CL 的 classes 不能),对象的表示类型也不能:你需要更多信息。
所以是的,类型有许多非常有用的用途,classes 无法满足这些用途。