此编程语言功能的名称是什么?是否有任何支持它的真实语言?
What is the name of this programming language feature and are there any real-world languages that support it?
让树数据结构这样定义:
一棵树有一个节点作为它的根。一个节点要么是一片叶子,要么是一个内部节点,它有一个或多个节点作为其子节点。
在某种伪 OO 编程语言中,我们可以这样定义一棵树:
Node := InnerNode | Leaf
Leaf {
isLeaf() : TRUE
}
InnerNode {
isLeaf() : FALSE
children() : List<Node>
}
Tree {
root() : Node
}
现在我们可以定义两个函数,'bad_code'和'good_code'。函数 'bad_code' 不编译,另一个函数编译:
function bad_code(Node anyNode) : void {
// this will give a compile time error "type Node does not define method children()"
anyNode.children();
}
function good_code(Node anyNode) : void {
// the compiler understands that all Nodes must have a method called isLeaf() which
// returns a boolean
let b : boolean <- anyNode.isLeaf();
if (b == FALSE) {
// this will not give a compile time error because the compiler can deduce that
// anyNode must be of type InnerNode which has the method children()
anyNode.children();
}
}
问题:
- 以上是否是以某种官方方式定义/描述的语言特性的示例?
- 如果是这样:这个语言功能的正式名称是什么?
- 现实世界中是否有实现此语言功能的编程语言?
- 此语言功能是否可以在运行时以零成本的编译时检查来实现?
你所描述的是编译器使用控制流图来缩小变量的类型,因此当 if
语句测试与变量类型相关的条件时,可以为 if
语句的主体推断出同一变量的更具体类型。
这称为控制流类型缩小,例如在Typescript。它纯粹是静态检查,在编译时完成,没有运行时损失;事实上,Typescript 中的类型在运行时根本不可用。
type TreeNode = InnerNode | Leaf
interface Leaf {
isLeaf: true
}
interface InnerNode {
isLeaf: false
children: Node[]
}
function bad_code(anyNode: TreeNode): void {
// type error: Property 'children' does not exist on type 'TreeNode'.
console.log(anyNode.children);
}
function good_code(anyNode: TreeNode): void {
if (!anyNode.isLeaf) {
// narrowed type to anyNode: InnerNode
console.log(anyNode.children);
}
}
请注意,Typescript 要求您以特定方式执行此操作;我们直接测试 anyNode.isLeaf
而不是先将其存储在变量 b: boolean
中,因为 Typescript 不会跟踪两个变量 b
和 anyNode
之间的关系:
function bad_in_typescript(anyNode: TreeNode): void {
let b: boolean = anyNode.isLeaf;
if (!b) {
// type error: Property 'children' does not exist on type 'TreeNode'.
console.log(anyNode.children);
}
}
此外,在上面的代码中 isLeaf
是一个 属性 而不是方法。 Typescript 确实有一个名为 user-defined type guards 的相关特性,它允许方法的 return 类型类似于 this is Leaf
,表明方法 returns true
仅当调用类型为 Leaf
:
时
type TreeNode = InnerNode | Leaf
interface BaseNode {
ifLeaf(): this is Leaf
isInner(): this is InnerNode
}
interface Leaf extends BaseNode {}
interface InnerNode extends BaseNode {
children(): Node[]
}
但是,Typescript 仍然比您的示例更受限制;我们必须测试 anyNode.isInner()
因为 !anyNode.isLeaf()
不一定会做同样的缩小。 (打字稿使用结构类型,所以实际上这个 Leaf
是 InnerNode
的超类型,这会导致联合类型出现一些问题。如果你给 Leaf
一个 属性 像 value: number
而 InnerNode
没有,那么 !anyNode.isLeaf()
将按照您的预期工作。)
让树数据结构这样定义:
一棵树有一个节点作为它的根。一个节点要么是一片叶子,要么是一个内部节点,它有一个或多个节点作为其子节点。
在某种伪 OO 编程语言中,我们可以这样定义一棵树:
Node := InnerNode | Leaf
Leaf {
isLeaf() : TRUE
}
InnerNode {
isLeaf() : FALSE
children() : List<Node>
}
Tree {
root() : Node
}
现在我们可以定义两个函数,'bad_code'和'good_code'。函数 'bad_code' 不编译,另一个函数编译:
function bad_code(Node anyNode) : void {
// this will give a compile time error "type Node does not define method children()"
anyNode.children();
}
function good_code(Node anyNode) : void {
// the compiler understands that all Nodes must have a method called isLeaf() which
// returns a boolean
let b : boolean <- anyNode.isLeaf();
if (b == FALSE) {
// this will not give a compile time error because the compiler can deduce that
// anyNode must be of type InnerNode which has the method children()
anyNode.children();
}
}
问题:
- 以上是否是以某种官方方式定义/描述的语言特性的示例?
- 如果是这样:这个语言功能的正式名称是什么?
- 现实世界中是否有实现此语言功能的编程语言?
- 此语言功能是否可以在运行时以零成本的编译时检查来实现?
你所描述的是编译器使用控制流图来缩小变量的类型,因此当 if
语句测试与变量类型相关的条件时,可以为 if
语句的主体推断出同一变量的更具体类型。
这称为控制流类型缩小,例如在Typescript。它纯粹是静态检查,在编译时完成,没有运行时损失;事实上,Typescript 中的类型在运行时根本不可用。
type TreeNode = InnerNode | Leaf
interface Leaf {
isLeaf: true
}
interface InnerNode {
isLeaf: false
children: Node[]
}
function bad_code(anyNode: TreeNode): void {
// type error: Property 'children' does not exist on type 'TreeNode'.
console.log(anyNode.children);
}
function good_code(anyNode: TreeNode): void {
if (!anyNode.isLeaf) {
// narrowed type to anyNode: InnerNode
console.log(anyNode.children);
}
}
请注意,Typescript 要求您以特定方式执行此操作;我们直接测试 anyNode.isLeaf
而不是先将其存储在变量 b: boolean
中,因为 Typescript 不会跟踪两个变量 b
和 anyNode
之间的关系:
function bad_in_typescript(anyNode: TreeNode): void {
let b: boolean = anyNode.isLeaf;
if (!b) {
// type error: Property 'children' does not exist on type 'TreeNode'.
console.log(anyNode.children);
}
}
此外,在上面的代码中 isLeaf
是一个 属性 而不是方法。 Typescript 确实有一个名为 user-defined type guards 的相关特性,它允许方法的 return 类型类似于 this is Leaf
,表明方法 returns true
仅当调用类型为 Leaf
:
type TreeNode = InnerNode | Leaf
interface BaseNode {
ifLeaf(): this is Leaf
isInner(): this is InnerNode
}
interface Leaf extends BaseNode {}
interface InnerNode extends BaseNode {
children(): Node[]
}
但是,Typescript 仍然比您的示例更受限制;我们必须测试 anyNode.isInner()
因为 !anyNode.isLeaf()
不一定会做同样的缩小。 (打字稿使用结构类型,所以实际上这个 Leaf
是 InnerNode
的超类型,这会导致联合类型出现一些问题。如果你给 Leaf
一个 属性 像 value: number
而 InnerNode
没有,那么 !anyNode.isLeaf()
将按照您的预期工作。)